【数据结构PTA 7-158-161】

本文涵盖了三个算法问题:7-158 数的计算,寻找满足特定条件的数的个数;7-159 xrf的镜子,解决项链镜像翻转的最短长度;7-160 分苹果,探讨不同方式将苹果分配到有限数量篮子的方案数。每个问题都详细描述了输入输出格式和样例,并提供了代码限制和时间内存限制。

7-158 数的计算

我们要求找出具有下列性质数的个数(包含输入的正整数 n)。先输入一个正整数 n,然后对此正整数按照如下方法进行处理:

1.本身不作任何处理;

2.在它的左边加上一个正整数,但该正整数不能超过原数的一半;

3.加上数后,继续按此规则进行处理,直到不能再加正整数为止。

例如输入n=6,
满足条件的数为:

6,16,26,126,36,136

输入格式:

1个正整数 n(n≤1000)。

输出格式:

1个整数,表示具有该性质数的个数。

输入样例:

在这里给出一组输入。例如:

6

输出样例:

在这里给出相应的输出。例如:

6

代码长度限制

16 KB

时间限制

1000 ms

内存限制

128 MB

#include<iostream>
using namespace std;
int arr[501];
int sum[501];
int n;
int main() {
	cin >> n;
	int t = n / 2;
	for (int i = 1;i <= t;i++) {
		arr[i] = sum[i / 2] + 1;
		sum[i] = sum[i - 1] + arr[i];
	}
	cout << (sum[t] + 1) << endl;
	return 0;
}

7-159 xrf的镜子

xrf有一个镜子,可以把任何接触镜面的东西变成原来的两倍——只是,因为是镜子嘛,增加的那部分是反的。比如一条项链,我们用AB来表示,不同的字母表示不同颜色的珍珠。如果把B端接触镜面的话,镜子会把这条项链变为ABBA。如果再用一端接触的话,则会变成ABBAABBA(假定xrf只用项链的某一端接触镜子)。给定最终的项链,请编写程序输出xrf没使用镜子之前,最初的项链可能的最小长度。

输入格式:

只有一个字符串,由大写英文字母组成(字母数<=100000),表示最终的项链。

输出格式:

只有一个整数,表示xrf没使用镜子前,最初的项链可能的最小长度。

输入样例:

ABBAABBA

输出样例:

2

代码长度限制

16 KbJava (javac)时间限制3500 ms内存限制128 MBPython (python3)时间限制2500 ms内存限制

128 MB其他编译器时间限制1000 ms内存限制64 MB

#include <bits/stdc++.h>
using namespace std;
// check函数用于返回s的前n个字符能够组成的最小长度
int check(string s, int n) {
    if (n % 2) return n; // n为奇数时,直接返回n
    for (int i = 0; i < n/2; i ++)
        if (s[i] != s[n-1-i])   // s不轴对称,直接返回n
            return n;
    return check(s, n/2);   // 递归进s的前n/2个字符进行判断
}
string s;
int n;
int main() {
    cin >> s;
    n = s.length();
    cout << check(s, n) << endl;
    return 0;
}

7-160 分苹果

这天风和日丽,万里无云的天空中飘着朵朵白云。在这样好的天气里,chocola准备去果园摘点苹果。

他一共摘了n个苹果,每个苹果各不相同,而他只携带了k个箱子用于装苹果。现在他想知道,将这n个不同的苹果放入k个箱子(每个箱子容量无限),你能告诉他一共有多少种不同的放法?(由于答案可能会很大,请输出答案对p取余后的结果)

输入格式:

仅一行,依次给出n,k,p三个整数,含义如题。

输出格式:

一个数,表示方案数对p求余的结果。

输入样例:

4 2 3

输出样例:

1

样例解释:

一共有4个苹果,2个篮子。
有以下7种方法

{1}{2,3,4};{2}{1,3,4};{3}{1,2,4};{4}{1,2,3};
{1,2}{3,4};{1,3}{2,4};

{1,4}{2,3}。

答案为7除以3的余数1。

数据范围:

n≤10000, k≤1000, k ≤ n

代码长度限制

16 KB

Java (javac)

时间限制

2500 ms

内存限制

256 MB

Python (python3)

时间限制

3000 ms

内存限制

256 MB

其他编译器

时间限制

1000 ms

内存限制

128 MB

import java.util.Scanner;

public class Main {

    private static int calc(int n){
        int d = 0;
        int next = -1;
        while (++d < 1000000 && next <= 0){
            // 最后一次分剩下的数量必然是n的倍数加1
            next = d * n + 1;
            for(int i = 0; i < n - 1; i++){
                if(next % (n - 1) != 0) {
                    next = -1;
                    continue;
                }
                next = next / (n - 1) * n + 1;
            }
        }
        return next;
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        while(cin.hasNextInt()) {
            int n = cin.nextInt();
            int count = calc(n);
            System.out.println(count);
        }
    }
}

7-161 间谍网络

由于外国间谍的大量渗入,国家安全正处于高度危机之中。如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。有些间谍接受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。

我们的反间谍机关提供了一份资料,包括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍,每个间谍分别用1到n的整数来标识。
请根据这份资料,判断我们是否可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。

输入格式:

第一行只有一个整数n。第二行是整数p。表示愿意被收买的人数。

接下来的p行,每行有两个整数,第一个数是一个愿意被收买的间谍的编号,第二个数表示他将会被收买的数额。

紧跟着一行只有一个整数r。然后r行,每行两个正整数,表示数(A,B)对 , A间谍掌握B间谍的证据。

输出格式:

如果可以控制所有间谍,第一行输出YES,并在第二行输出所需要支付的贿金最小值。否则输出NO,并在第二行输出不能控制的间谍中,编号最小的间谍编号。

输入样例:

2
1
2 512
2
1 2
2 1

输出样例:

YES
512

数据范围提示

1<=n<=3000,1<=p<=n,1<=r<=8000, 每个收买的费用为非负数且不超过20000。

代码长度限制

16 KB

Java (javac)

时间限制

2000 ms

内存限制

256 MB

Python (python3)

时间限制

2000 ms

内存限制

256 MB

其他编译器

时间限制

1000 ms

内存限制

64 MB

#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
struct edges
{
    int u,v,next;
}edge[maxn];
int head[maxn],dfn[maxn],low[maxn],ind[maxn],val[maxn],f[maxn];
int cnt,tot,sum,n;
stack<int> s;
bool vis[maxn];
void addedge(int u,int v)
{
    edge[cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void Tarjan(int num)
{
    dfn[num]=low[num]=++tot;
    vis[num]=true;
    s.push(num);
    for(int i=head[num];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(!dfn[v])
        {
            Tarjan(v);
            low[num]=min(low[v],low[num]);
        }
        else if(vis[v])
        {
            low[num]=min(low[num],dfn[v]);
        }
    }
    if(dfn[num]==low[num])
    {
        sum++;
        while(true)
        {
            int now=s.top();
            s.pop();
            vis[now]=false;
            ind[now]=sum;
            if(now==num) break;
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d",&n);
    int m,i;
    scanf("%d",&m);
    memset(val,-1,sizeof(val));
    memset(head,-1,sizeof(head));
    for(i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        val[u]=v;
    }
    scanf("%d",&m);
    for(i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        addedge(u,v);
    }
    for(i=1;i<=n;i++)
    {
        if(!dfn[i]) Tarjan(i);
    }
    for(i=1;i<=n;i++)
    {
        for(int j=head[i];j!=-1;j=edge[j].next)
        {   int v=edge[j].v;
            if(ind[i]!=ind[v])
            {
                f[ind[v]]++;
            }
        }
    }
    int ans=0;
    for(int i=1;i<=sum;i++)
    {
        if(!f[i])
        {   int minum=1e9;
            for(int j=1;j<=n;j++)
            {
                if(ind[j]==i)
                {
                    if(val[j]!=-1&&val[j]<minum)
                    {
                        minum=val[j];
                    }
                }
            }
            if(minum==1e9)
            {
                printf("NO\n");
                for(int j=1;j<=n;j++)
                {
                    if(ind[j]==i)
                    {
                        printf("%d\n",j);
                        return 0;
                    }
                }
            }
            ans+=minum;
        }
    }
    printf("YES\n");
    printf("%d\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值