蓝桥双周赛 第 17 场 小白入门赛

前言

这个比赛真的唐完了!!!!!

虽然就写了一个小时(前一个小时去和朋友吃饭了),但是就过了两题你敢信,真的不难的说

待我与你细细说来 我的唐人史

正文

桃园结义

打卡题,输出3即可,毕竟桃园三结义嘛

#include <iostream>
using namespace std;
int main()
{
  cout<<3;// 请在此输入您的代码
  return 0;
}

2  北伐军费   

 

这个题和之前cf上一道题有点像

每个人都会拿当前的最大值,但是这个是每次拿他都会乘-1

不过我们可以发现其实选了两次之后就会变成原数组,比如1 2 3

A 选3,变成-1 -2 然后B选-1 变成 2,其实还是选的原来的数组

因此 对于A 来说他会选原数组的最大的,对于B来说,他会选原数组相反数的最大的(也就是最小的),所以其实可以进行排序后A从大到小加,B从小到大加 小的数的相反数(对于他就是大的)

然后最后A-B

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    int n;
    cin >> n;
    int s1 = 0, s2 = 0, a[10000];
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    sort(a + 1, a + 1 + n);
    for (int i = 1; i <= n / 2; i++) {
        s1 += -a[i];
        s2 += a[n - i + 1];
    }
    if (n % 2)
        s2 += a[(int)n / 2 + 1];
    cout << s2 - s1 << endl;
    return 0;
}

但是还没完哈,赛后我看了看其他人的代码,发现一个更妙的做法,我们对于B是每次加原数组的一个相反数,然后我们最后又进行A-B,那么其实B又反回来了,所以其实最后的答案就是数组和

(对的没错,就是数组和,自己推一下就可以看出来了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    int n;
    cin >> n;
    int s,x;
  s=0;
    for (int i = 1; i <= n; i++) {
        cin >> x;s+=x;
    }
  cout<<s;
    return 0;
}

3 挑选武将

从这里就开始唐B了,,,难绷

题干的意思是 最多有多少个单独来自一个军营的士兵

我以为的意思 最少有多少个士兵来自同一军营

一直调过不了啊!!!!题干读错了真滴难绷

然后这个题也是不难,首先每个人来自军营的编号并不重要,我们可以把他们存起来,然后降序排序,并且为了确保尽可能多的的士兵是单独的,我们尽量先把人最多的营的士兵都找过来,这样就可以尽可能减少对不同兵营的消耗,就是这样

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int num[100005];

int main() {
	int x, n, k, sum, r, ans = 0;
	cin >> n >> k;
	for (int i = 0; i < n; i++) {
		cin >> x;
		num[x]++;
	}
	sort(num, num + 100003, greater<int>());
	for (int i = 100002; i >= 0; i--)
		if (num[i]) {
			ans = r = i + 1;
			break;
		}
	if (ans >= k) {
		cout << k << endl;
		return 0;
	}
	k -= ans;
	for (int i = 0; i <= r; i++) {
		ans--;if (k - num[i] + 1 <= 0)
			break;
		k = k - num[i] + 1;
		
	}
	cout << ans;
	return 0;
}

4 三顾茅庐

这道题我也看了,但是唐的更离谱。。。

这个题如果都是x减完以后如果都是正的就直接输出即可,关键在于如果会减到负数怎么办捏

首先我们可以把x减到最小的正数,也就是再减就会变成负数的情况,此时一定会有x<y

那么如果这时候再进行|x-y|,实际上就会变成y-x,然后对于y-x,如果再进行y-(y-x)就会变成x

不难发现这里是一个循环

所以我们其实需要看这个时候的k剩下的如果是奇数那么最后就会剩一个y-x否则就是x

然后就过了,那么为什么会唐呢?

这里是一个多组  我在特判的时候直接进行break操作了!!!!!

真的受不了赛后改成continue就对了,以后多组还是直接外接slove函数直接return 吧呜呜呜

5 逆天改命

这个其实就是对一个0数组进行操作来看可不可以到一个新的数组

然后有区间有0才能加,区间可以随便减

那么其实我们完全可以对一个数进行减的操作,使他减到合适的数,所以我们可以先把数组都变得很大,然后再每个自己去减

但是我们发现有0才能加啊,所以需要有一个数做出贡献,一直对自己进行减的操作变成0,然后别的数都满足了以后,这个0最多可以自己加到1,所以有一个数最多是1,其他都可以

结论就是,如果数组有0或者1那么就是OK,否则就不行

#include <iostream>
using namespace std;

int main() {
	int t, s, x, n;
	cin >> t;
	while (t--) {
		cin >> n;
		s = 0;
		while (n--) {
			cin >> x;
			if (x == 1 || x == 0)
				s = 1;
		}
		if (s)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	// 请在此输入您的代码
	return 0;
}

6 智算士气

这道题用到了质因数分解的思想

首先我们需要知道 任何一个数都可以被分解成,k个质数相乘的形式

 pi^ai 从1k连乘的形式 那么对于每一个pi,我们都可以选择取m个pi (0<=m<=ai)那么就有1+ai种可能 然后有n个队伍要取 所以一共有 (1+ai)^n种情况

但是他需要所有数的最小公倍数是m,那么我们还需要保证对于每个质数pi 都有一个数把他选到pi^ai的形式,只有这样所有数的最小公倍数才会是m

所以对于每个质数,我们真正可以取得情况是(1+ai)^n-ai^n

也就是从0~ai里面去掉只选0~(ai-1)的情况,就是至少有一个数选ai的情况数 然后对于每个pi的情况都乘起来就是ans了

但是注意取模过程要用快速幂,而且在计算的过程也要实时取模,不然一定会wa掉,好像还要开ll

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353;

ll fpow(ll n, ll k) {
    ll res = 1;
    while (k) {
        if (k & 1)
            res = res * n % mod;
        n = n * n % mod;
        k >>= 1;
    }
    return res;
}

int main() {
    ll n, m, s, ans = 1;
    cin >> n >> m;
    for (int i = 2; i <= m / i; i++) {
        if (m % i == 0) {
            int s = 0;
            while (m % i == 0)
                m /= i, s++;
            ans = (ans % mod * (fpow(s + 1, n) - fpow(s, n)) % mod + mod) % mod;
        }
    }
    if (m > 1)
        ans = (ans % mod * (fpow(2, n) - fpow(1, n)) % mod + mod) % mod;
    cout << ans % mod << endl;
    return 0;
}

PS:这里我想说一个问题,取模经常要用(x%mod+mod)%mod

这个为什么呢?

其实就是为了防负数出现,那我们为啥会有负数出现呢?

拿这个题举例,虽然好像(1+ai)^n-ai^n一定是正的啊, 但是我们在快速幂的时候,取模后的模数就不清楚到底哪个大了,就可能出现负数的情况,所以还是要取模滴

后记

这个比赛真的蚌埠住了,这么简单的题.....

不过会了就好,继续补题吧,这个也给我一个很真实的警告,编程容不得半点差错啊!!!

望诸君共勉

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值