Problem - D - Codeforces
这题比赛的时候用dfs打了个全排列,有点猜的成分..然后就猜对了
在比赛过程中没有验证其正确性,今天看了题解,发现确实证明的很好!!
1..其中n只能放在第一位:
用反证法证明 b(i+1)=(bi+n)%n=bi,所以n只能放在第一位
2.n为奇数时候没有构造方案
1+2+3...+n=(n+1)*n/2,模n答案为0,又第一位只能放n答案也为0,故不行
3.当n为偶数的时候,发现构造
1 ,n ,2 ,n-1 ,3,n-2是一个好的构造方法..不会证明比赛时候看样例猜的
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
Problem - E - Codeforces
挺可惜的一道题目...
比赛时候差一点就出了(???差一点??)
其实我有个地方考虑不周...
看样例知道n为奇数时候一定无解
当n为偶数时,我们统计每一个字母出现的次数,如果出现次数>n/2,一定无解,因为一定有这个字母的配对!!!
否则我们就统计每个配对的种类和个数
因为每个种类数和另外种类的交换,花费1但是同时减去2个配对,所以这个是最优的
,如果只剩下一种了,那么每个配对花费1(比赛时我还考虑是否交换之后是否一定不出现矛盾
比如abaa,aa和ab交换后出现矛盾)事实上是不会的,因为出现矛盾的情况一定是某个字母出现的次数>n/2的情况了
比赛过程中有个地方没有考虑情况:
每个种类只能和其他种类配对,但是不一定只能和一种配对(这不是最优的)
比如 aa aa bb bb cc cc,最小花费为3(aa和cc aa和bb ,bb和cc)
但我考虑的最小花费为4(aa和bb,aa和bb,然后cc在单独交换)
比赛过程中我写的....
for(auto it =mp.begin();it!=mp.end();it++){
if(it->second!=0){
for(auto k=mp.begin();k!=mp.end();k++){
if(k->first!=it->first&&k->second!=0){
if(it->second>k->second){
it->second= it->second- k->second;
ans=ans+k->second;
k->second=0;
}else{
ans=ans+it->second;
k->second=k->second-it->second;
it->second=0;
break;
}
}
}
}
}
for(auto it=mp.begin();it!=mp.end();it++){
if(it->second!=0)ans=ans+it->second;
}
其实我们只需统计出现最多配对种类cnt,和总的配对数目sum
如果2*cnt>=sum,答案为cnt
否则答案为(sum+1)/2(如果sum为奇数的话,需要多加1)
仔细想想还是很好理解的
正解:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
Problem - C - Codeforces
今天晚上vp做的,没思路啊!!
刚刚补完这题..居然是dfs...
初始化:
字符串s统计所有字符
cin>>n>>k;
for(int i=0;i<30;i++)vis[i]=0;
cin>>a>>b;
setq;
for(int i=0;i
主要看下dfs吧,
pos为到了第几个位置,cnt为一共标记了几个字母
void dfs(int pos,int cnt){
if(pos==s.size()){
if(cnt==k)ans=max(ans,calc());
return ;
}
dfs(pos+1,cnt);
vis[s[pos]-97]=1;
dfs(pos+1,cnt+1);
vis[s[pos]-97]=0;
}
计算
我们发现长度为x的字串对答案的贡献为(x+1)*x/2
ll ans=0;
ll now=0;
for(int i=0;i
其实比赛过程中我就注意到了可以枚举k的字母的选取,我想暴力取的...
种类数为C26 k,最大的数好像才84,987,760...不会超时啊!!!
比赛时候没有算清楚啊!!!
回去休息了..
明天见