CQUPT WEEKLY TRAINING (6)DIV2 解题报告

A题:IQ test,23333。就是给你n个数,求出一个跟其他数不一样的数的下标。
很明显,不同是根据奇偶区分。然后就容易了。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>

using namespace std;

int a[105];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int x,y;
        x=0,y=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]%2==0)
                x++;
            else
                y++;
        }
        if(x > y)
        {
            for(int i=0;i<n;i++)
            {
                if(a[i]%2!=0)
                    printf("%d\n",i+1);
            }
        }else{
            for(int i=0;i<n;i++)
            {
                if(a[i]%2==0)
                    printf("%d\n",i+1);
            }
        }
    }
    return 0;
}

B题:给你一串数字。代表着电话号码,问你能不能分解成2个或者3个一组的,用“-”区分。
第一下看到的题感觉是处理字符串,再想想构造方案的时候,以为是数论。就是把100以内的数学分解为2 3 这两个数组相加的和,然后再想想其实没有不存在的情况。
如果n为偶数,那么我全部分为2个一组的。如果为奇数,我就分为(n-1)/2-1组2个的,然后把剩下的两个和多出来的一个构造为第三个。这样就可以了。
题目很水,但是很有启发性,我如果把范围加大,然后把2和3这两个数字改一下。大家可以思考一下?

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>

using namespace std;

char a[105];
int main()
{
    int n;
    while(cin>>n)
    {
        cin>>a;
        if(n%2 == 0)
        {
            for(int i=0;i<n;i++)
            {
                cout<<a[i];
                if(i%2 == 1&&i != n-1)
                    cout<<"-";
            }
            printf("\n");
        }else{
            for(int i=0;i<n-3;i++)
            {
                cout<<a[i];
                if(i%2 == 1)
                    cout<<"-";
            }
            cout<<a[n-3]<<a[n-2]<<a[n-1];
            printf("\n");
        }
    }
    return 0;
}

C题:给一个数,如果它能分解为2个素数乘积。注意18=2*2*3 这种也算只有2个。
然后我居然发现这个跟上面题有点异曲同工的感觉,上一题是和,这道题是乘积。就无脑枚举就可以了吧,也可以打个3000以内的素数表搞,我是边枚举一个数,边更新n的。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>

using namespace std;

bool check(int x) {
    int num = 0;
    for (int i = 2; i * i <= x; ++i) {
        if (x % i == 0) {
            ++num;
            while (x % i == 0)
                x /= i;
            if (x == 0)
                break;
        }
    }
    if (x != 1) ++num;
    return num == 2;
}

int main() {
    int n;
    while (scanf ("%d", &n) != EOF) {
        int res = 0;
        for (int i = 6; i <= n; ++i)
            res += check(i);
        printf ("%d\n", res);
    }
    return 0;
}

D题:大概就是一个括号匹配吧。
可以用stack搞,貌似貌似这里计数就可以了,这道题我反正是想复杂了。这里给个很不错的解法,见CODE。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>

using namespace std;


const int MAXN = 1001000;
char s[MAXN];

int main()
{
    scanf("%s", s);
    int cnt = 0;
    int sc = 0;
    for(int i = 0; s[i]; ++i)
    {
        if (s[i] == '(')
        {
            sc++;
            cnt++;
        }
        else
        {
            if (sc > 0)
            {
                sc--;
                cnt++;
            }
        }
    }
    cnt -= sc;
    printf("%d\n", cnt);
    return 0;
}

E题:统计2到n区间内的数,该数可以分解为两个素数和+1。如果这样的数字个数大于等于k Yes 否则 NO。
统计区间满足这样情况的数,然后check一下。这里可以直接把范围内的数字打表出来,然后对应输入check输出答案即可


#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>

using namespace std;

int ans[1005], prime[1005];

int is_prime(int n)
{
	for (int i = 2; i <= sqrt(n); ++i)
		if(n % i == 0)
			return 0;
	return 1;
}

int init()
{
	int k = 0;
	memset(ans, 0, sizeof(ans));

	for (int i = 2; i <= 1000; ++i)
		if(is_prime(i))
			prime[k++] = i;
	for (int i = 0; i < k-1; ++i) {
		int m = prime[i]+prime[i+1]+1;
		if(is_prime(m))
			ans[m]++;
	}


	for (int i = 1; i <= 1000; ++i)
		ans[i] += ans[i-1];

	return 0;
}

int main()
{
//	freopen("a.in", "r", stdin);
//	freopen("a.out", "w", stdout);
	init();
	int n, k;
	cin >> n >> k;
	if(ans[n] >= k)
		cout << "YES" << endl;
	else
		cout << "NO" << endl;

	return 0;
}

F题:这题是求一个类似最小生成树的东西。但是是有限制的MST。

预处理的时候就把数据处理一下,然后按照kruskal算法的思路搞下来。不太好讲,估计得你们自己啃下这题。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

struct Node
{
    int a,b;
    int cost;
}node[10010];


bool cmp(Node a,Node b)
{
    return a.cost<b.cost;
}
bool f[1010];
int v[1010];


int main()
{int n,m,a,b,c;
    while(cin>>n)
    {memset(node,0,sizeof(node));
     memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++)
        scanf("%d",&v[i]);

        cin>>m;
        int num=0;
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);

            if(v[a]>v[b])
            {
                node[num].a=a;
                node[num].b=b;
                node[num++].cost=c;
            }
        }


        sort(node,node+num,cmp);
        long long ans=0;
        int num1=0;
        for(int i=0;i<num;i++)
        {
            if(!f[node[i].b])
            {
                ans+=node[i].cost;
                f[node[i].b]=1;
                num1++;
            }
        }



        if(num1==n-1)
        {
            cout<<ans<<endl;
        }
        else cout<<"-1"<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值