a搬砖之余看到了几个月前报名的百度之星初赛的短信通知,emmm,那就参加试试吧。就搞定了前两题,记录一下吧
第一题.签到
题目链接
思路:
通过下面的k依次变大,我们可以得到下面两个公式
a | b | k |
---|---|---|
a | b | 0 |
a+b | a-b | 1 |
2a | 2b | 2 |
2(a+b) | 2(a-b) | 3 |
4a | 4b | 4 |
4(a+b) | 4(a-b) | 5 |
.... | .... | .... |
2(k/2)*(a+b) | 2(k/2)*(a-b) | k%2==1 |
2(k/2)*a | 2(k/2)*b | k%2==0 |
但是这里的k很大,并且结果还要取模,所以我们这里应该用快速幂去求。
但是在这里我没有注意到负数取模的问题,所以一直不知道哪里错,最后看了题目下面的提问才知道。对于(a-b)可能出现负数,比如(-3)%10,程序算的会是-3,而正确的应该是(-3)%10+10 = 7,代码里我们让它再加上一下我们取的模就可以了。
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 998244353;
ll Pow(ll a, ll b)
{
ll sum = 1;
while (b) {
if (b & 1) {
sum = (sum * a) % mod;
b--;
}
b /= 2;
a = a * a % mod;
}
return sum;
}
int main()
{
int t;
cin >> t;
while(t--){
ll a,b,k;
ll a1,b1;
cin >> a >> b >> k;
if(k%2==1){
a1 = (((a+b)%mod)*Pow(2,k/2))%mod;
b1 = (((a-b+mod)%mod)*Pow(2,k/2))%mod;
}
else{
a1 = (Pow(2,k/2)*a)%mod;
b1 = (Pow(2,k/2)*b)%mod;
}
cout << a1 << " " << b1 << endl;
}
return 0;
}
第二题.随机题意
题目链接
思路
这是一道贪心的题目,主要思想是对a数组排序一下,对于每个a[i], b[i]满足我们贪心要求的取值范围是 [a[i]-k,a[i]+k] ,我们每次取我们能取到的最小的那个数,通过设置一个min_x来记录上次b[i]取的数,我们就在当前范围取一个最小且比min_x大的数,如果取不到就继续下面的b[i],统计能取到的数的个数,就是答案。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int main()
{
int t;
cin >> t;
while(t--){
int n,k;
cin >> n >> k;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);//cin >> a[i];这里使用C的scanf,不然会超时
sort(a,a+n);
int cnt = 0;
int min_x = a[0]-k-1;
for(int i=0;i<n;i++){
int Max = a[i]+k;
int Min = a[i]-k;
if(Min<=min_x && min_x<Max){
cnt++;
min_x++;
}
else if(Min>min_x){
cnt++;
min_x = Min;
}
}
cout << cnt << endl;
}
return 0;
}
官网答案更新了-->答案
溜了溜了,继续搬砖去了