cf比赛链接
目录
A. Divide and Conquer
题意:
思路:
代码:
B. Make Array Good
题意:
思路:
代码:
C. Binary Strings are Fun(什么疑惑题面)
题意:首先的两个定义:
思路:
代码:
A. Divide and Conquer
题意:
给你n个数,如果这n个数的和为偶数,那么这个数组是“好的”,否则我们可以对他的任意一个数执行一次操作:使任意一个数变成他的.问你至少需要进行几次操作(可能是0),才可以使这个数组变成“好的”。
思路:
首先把所有数组的指加起来,如果是偶数就直接输出0,如果不是的话就说明要进行操作,
因为执行操作后要保证删去的和是一个奇数,那么我们删掉的数是一个奇数的时候退出即可
那么对于每一个数,循环进行操作,当删去的数是一个奇数的时候就退出保存答案,然后取答案的最小值即可。
代码:
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;
const int N=1000000+100;
int n ,m,h;
ll s[N];
void slove()
{
cin>>n;
ll k=0;
for(int i =1;i<=n;i++)
{
cin>>s[i];
k+=s[i];
}
if(k%2==0){
cout<<0<<endl;
return ;
}
int res=1e9;
for(int i =1;i<=n;i++)
{
int sum=0;
int k=s[i];
while(1)
{
if((k-s[i])%2)break;
s[i]/=2;
sum++;
}
res=min(sum,res);
}
cout<<res<<endl;
}
int main()
{
int t;
sc_int(t);
while(t--)slove();
return 0;
}
B. Make Array Good
题意:
给你n个数,你可以给每一个扩大0-范围内任意的数,问你每一个数扩大多少可以使任意的两个数的最大值是他们的最小值的倍数。
思路:
因为可以证明这样的序列是一定存在的,那么就说明排序后相邻两个数的倍数最少可以是2,那么我们先从小到大排序,对于排序之后的数对于第一个数不处理,从第二个数开始,把他变成前一个数的两倍(因为一定存在,那么一定可以变),这样子再把处理的数存到下标之中,之后按下标输出结果即可。
代码:
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;
const int N=1000000+100;
int n ,m,h;
ll s[N];
struct lk{
int x;
int i;
int res;
}cnt[N];
map<int,int>q;
bool cmp(lk x ,lk y ){return x.x<y.x;}
void slove()
{
q.clear();
cin>>n;
ll ma=0;
for(int i=1;i<=n;i++)
{
cin>>cnt[i].x;
cnt[i].i=i;
}
sort(cnt+1,cnt+1+n,cmp);
for(int i =1;i<=n;i++)
{
if(i==1)
{
cnt[i].res=0;
cnt[i].x+=cnt[i].res;
q[cnt[i].i]=cnt[i].res;
}
else {
cnt[i].res=cnt[i-1].x-(cnt[i].x%cnt[i-1].x);
cnt[i].x+=cnt[i].res;
q[cnt[i].i]=cnt[i].res;
}
}
cout<<n<<endl;
for(int i =1;i<=n;i++)
cout<<i<<" "<<q[i]<<endl;
}
int main()
{
int t;
sc_int(t);
while(t--)slove();
return 0;
}
C. Binary Strings are Fun(什么疑惑题面)
题意:首先的两个定义:
一:字符串的好的定义:给一个长度为m奇数的字符串,如果对于所有的奇数i()a_i是前i个字符出现最多的那个字符,那么这个字符串就是好的.
二:字符串s的拓展(长度为m),如果有一个长为2m-1的字符串k,并且满足=(1<=i<=m)
那么k就是s的一个拓展。如
1011011就不是1001的拓展。
现在给你一个字符串s问你它的的好的拓展的情况的和是多少(对998244353取模),就是求每字符串的前缀的良好的拓展的情况之和。
思路:
是一个dp问题,用dp[N]代表前n项的字符串的答案,那么我们可以分析:对于所有的情况,如果满足,那么dp[i]一定为1(假如是1-是0那么前i-1项的和一定是0比1多,然后因为后面要满足1比0多,所以至少要两个0才能满足条件,即只有一种情况),那么如果不相等就一定是dp[i-1]*2了,然后每次取一下模就可以了
代码:
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;
const int N=1000000+100,mod=998244353;
int n ,m,h;
char s[N];
ll dp[N];
void slove()
{
cin>>n;
cin>>s+1;
dp[1]=1;
ll res=1;
for(int i=2;i<=n;i++)
{
if(s[i]!=s[i-1])
dp[i]=1;
else
dp[i]=(dp[i-1]*2)%mod;
res=(res+dp[i])%mod;
}
cout<<res<<endl;
}
int main()
{
int t;
sc_int(t);
while(t--)slove();
return 0;
}