【Codeforces】Codeforces之丰【部分题解】
Codeforces之丰
[by_041]
文章目录
- Codeforces之丰
- [by_041]
- @[toc]
- Codeforces Round #721 (Div. 2)
- A. And Then There Were K
- B1. Palindrome Game (easy version)
- B2. Palindrome Game (hard version)
- Codeforces Round #723 (Div. 2)
- A. Mean Inequality
- B. I Hate 1111
- C1. Potions (Easy Version)
- C2. Potions (Hard Version)
- D. Kill Anton
Codeforces Round #721 (Div. 2)
Codeforces Round #721 (Div. 2)
A. And Then There Were K
Problem - A - Codeforces
- 题意是求满足【n&(n−1)&(n−2)&(n−3)&...(k)=0n\&(n−1)\&(n−2)\&(n−3)\&...(k)=0n&(n−1)&(n−2)&(n−3)&...(k)=0】要求最大的k值
- 位运算→二进制下处理
- 要与后所有位是0,k在n最高位处是0,而在这个过程中一定会经过只有此位为1的数(2x,x=floor(log2n)2^x,x=floor(log_2n)2x,x=floor(log2n)),所以只要输出【2x−12^x-12x−1】就行了
#include<bits/stdc++.h>using namespace std;int main()
{int T,n,nn,i;bitset<10>num;cin>>T;while(~scanf("%d",&n)){nn=1;i=n;while(i>>=1)nn<<=1;printf("%d\n",nn-1);}return 0;
}
B1. Palindrome Game (easy version)
Problem - B1 - Codeforces
题意就是给一个01字串每次可以进行两种操作
- 花费1dollar:将一个0转化为1
- 不花费:将字串reverse,前提是上一步不是reverse而且当前串不回文
Alice先手,Bob后手,字串全为1结束,俩人都是智者,对于给出的情况判断谁稳赢
对于 easy version 给出的字串原本就是回文的
明显博弈论,首先看看以前的经验:
- 博弈论解法:
- 确定其中一方必胜情况
- 增加一步反转情况
- 重复2操作,反推得到给出现状的博弈结果
- 实现博弈结果判定
- 博弈论解法:
对于0有两种情况:
- cas1 : …0…|…0…(对称位置也是0)
- cas2 : …0…|…1…(对称位置不是0)在此处的原串中不会出现就是了
没有0:一定平局
对于只有cas1的0又分为两种情况:
处理一般的 …0…|…0… ,必需要当下的选手付出1dollar
- 另一方旋转(reverse),此方再付1dollar,将剩下同样的情况还给对方,虽致使对方可能在下一步(如果有,即还有0的情况下)要至少再付出1dollar,不过对于最后一手来说是对方赚(2dollar)的,所以对方会引导最后的这一步发生在该方的步子里
- 或者,另一方付出1dollar,将剩下同样的情况继续留给次方,这样付出相平,在不改变手顺的情况下去除了一个cas1的情况
由此,当场面只有这种非对称中心的对称的一对或几对0存在时,先手将亏2dollar,后手胜
对于处理对称中心是0的情况
- Alice若在第一步选择花费1dollar将其转化为0,就成为了只有上一种情况的后手,在有上一种情况的时候A赚2-1=1dollar,A必胜,在没有上一种情况的时候A亏1dollar,B必胜
- 若A不转化,因为原串为回文串,必须转化一个0到1,其他的选择只会更劣
因为是 easy version 所以只需要考虑cas1存在的情况,cas2存在的情况放到 hard version 考虑
#include<iostream>using namespace std;int main()
{int T,n,cas1,cas2,anss=0;//anss means is good to Alicechar str[1007];cin>>T;while(T--){scanf("%d",&n);getchar();for(int i=0;i<n;i++)str[i]=getchar();str[n]='\0';// cout<<str<<endl;cas1=cas2=0;for(int i=0,m=(n+1)/2-1;i<=m;i++){if(str[i]==str[n-i-1]){if(str[i]=='0'){cas1+=2;//..0..|..0.. *2}}else//B1 will no come to this{cas2++;//..1..|..0.. or ..0..|..1..}}cas1-=((n&1)&&(str[(n+1)/2-1]=='0'));
// printf("cas1 = %2d ; cas2 = %2d ;\n",cas1,cas2);anss=(cas1&1?(cas1==1?-1:1):(cas1==0?0:-2));if(cas2>0){if(anss>=0)anss+=cas2;elseanss=cas2-2+abs(anss);}if(anss){if(anss>0)puts("ALICE");elseputs("BOB");}elseputs("DRAW");}return 0;
}
B2. Palindrome Game (hard version)
Problem - B2 - Codeforces
题意还是给一个01字串每次可以进行两种操作
- 花费1dollar:将一个0转化为1
- 不花费:将字串reverse,前提是上一步不是reverse而且当前串不回文
Alice先手,Bob后手,字串全为1结束,俩人都是智者,对于给出的情况判断谁稳赢
对于 hard version 给出的字串不一定原本就是回文的
同上,对于0有两种情况:
- cas1 : …0…|…0…(对称位置也是0)
- cas2 : …0…|…1…(对称位置不是0)在此处的原串中不会出现就是了
没有0:一定平局
对于只有cas1的0又分为两种情况:
处理一般的 …0…|…0… ,必需要当下的选手付出1dollar
- 另一方旋转(reverse),此方再付1dollar,将剩下同样的情况还给对方,虽致使对方可能在下一步(如果有,即还有0的情况下)要至少再付出1dollar,不过对于最后一手来说是对方赚(2dollar)的,所以对方会引导最后的这一步发生在该方的步子里
- 或者,另一方付出1dollar,将剩下同样的情况继续留给次方,这样付出相平,在不改变手顺的情况下去除了一个cas1的情况
由此,当场面只有这种非对称中心的对称的一对或几对0存在时,先手将亏2dollar,后手胜
对于处理对称中心是0的情况
- Alice若在第一步选择花费1dollar将其转化为0,就成为了只有上一种情况的后手,在有上一种情况的时候A赚2-1=1dollar,A必胜,在没有上一种情况的时候A亏1dollar,B必胜
- 若A不转化,因为原串为回文串,必须转化一个0到1,其他的选择只会更劣
对于有cas2的情况:
Alice看到当前局面不是回文串高兴坏了,立马连续cas2次选择反转(reverse)操作,Bob只得cas2次花费1dollar消除这种情况使自己早日推理连续亏损的状态
到最后一次时
- 若Alice放弃翻转字串,用1dollar选择将最后一个不对称的0转化为1,则会让Bob面临上面只有cas1的情况
- 若A继续反转,则会让自己面临只有cas1的情况
我们可以看到,在只有cas1的时候,先手的结局有亏2dollar、亏1dollar和赚1dollar,而Alice为了让自己得利,会在只剩cas1后手有利时放弃最后一次的翻转,否则不然
根据上述分析就能算出A最后的亏盈(在下方程序中的anss)了,根据正负性判断结果输出即可
#include<iostream>using namespace std;int main()
{int T,n,cas1,cas2,anss=0;//anss means is good to Alicechar str[1007];cin>>T;while(T--){scanf("%d",&n);getchar();for(int i=0;i<n;i++)str[i]=getchar();str[n]='\0';// cout<<str<<endl;cas1=cas2=0;for(int i=0,m=(n+1)/2-1;i<=m;i++){if(str[i]==str[n-i-1]){if(str[i]=='0'){cas1+=2;//..0..|..0.. *2}}else{cas2++;//..1..|..0.. or ..0..|..1..}}cas1-=((n&1)&&(str[(n+1)/2-1]=='0'));
// printf("cas1 = %2d ; cas2 = %2d ;\n",cas1,cas2);anss=(cas1&1?(cas1==1?-1:1):(cas1==0?0:-2));if(cas2>0){if(anss>=0)anss+=cas2;elseanss=cas2-2+abs(anss);}if(anss){if(anss>0)puts("ALICE");elseputs("BOB");}elseputs("DRAW");}return 0;
}
Codeforces Round #723 (Div. 2)
- Codeforces Round #723 (Div. 2)
A. Mean Inequality
Problem - A - Codeforces
题意就是给2n2n2n个数排成环,要求一个排列使得相邻的三个数不等差(不存在一个数是两侧数的平均数)
把该数组分为排序后均分为两个长度为n的部分(大于中位数和小于中位数的),交叉摆放就行(大的中间夹的都是小的,小的中间夹的都是大的),因为大的的平均数一定大于中位数,小的的平均数一定小于中位数,所以这样是一定可行的
注意初始数组(未拆分前)分配空间要有2n个元素
#include<bits/stdc++.h>using namespace std;int main()
{int T,n,nn,a[55],b[55];//空间啊啊啊啊啊啊,2n啊啊啊啊cin>>T;while(T--){scanf("%d",&n);nn=n*2;for(int i=0;i<nn;i++)scanf("%d",a+i);sort(a,a+nn);for(int i=0;i<n;i++)b[i]=a[i+n];printf("%d %d",a[0],b[n-1]);for(int i=1;i<n;i++)printf(" %d %d",a[i],b[n-i-1]);putchar('\n');}return 0;
}
B. I Hate 1111
Problem - B - Codeforces
题意是给T个数,分别判断每个数能否被拆分成若干个{11,111,1111,11111,...}\{11,111,1111,11111,...\}{11,111,1111,11111,...}的和
由于{1111,11111,...}\{1111,11111,...\}{1111,11111,...}都可以被{11,111}\{11,111\}{11,111}组成,所以只要看其被减去若干个111后存不存在被11整除的情况即可
所以问题就变成了是否存在俩正整数使得【111×a+11×b=n111\times a+11\times b=n111×a+11×b=n】成立,于是就有了以下俩方法:(分别O(n111)、O(1)O(\frac n{111})、O(1)O(111n)、O(1))
#include<bits/stdc++.h>using namespace std;//1111,11111,111111...都可以被111和11组成,所以只要拆分成若干的111和11就行int main()
{int T,n;cin>>T;while(T--){scanf("%d",&n);while(n>=0){if(n%11==0){puts("YES");n=0;break;}n-=111;}if(n)puts("NO");}return 0;
}
#include<bits/stdc++.h>using namespace std;//1111,11111,111111...都可以被111和11组成,所以只要拆分成若干的111和11就行int main()
{int T,n;cin>>T;while(T--){scanf("%d",&n);int x111=n%11; //111=11*10+1,所以n可拆分成111和11的时候111的数是可以直接算的n-=x111*111;if(n>=0&&n%11==0)puts("YES");elseputs("NO");}return 0;
}
C1. Potions (Easy Version)
- Problem - C1 - Codeforces
C2. Potions (Hard Version)
Problem - C2 - Codeforces
俩题一样,就是C2数据范围比C1大
题意是给一串数列,一人从左往右走一遍,中间可以选择是否选取走到的数字,过程中不能出现所拿的数字是负数,求到终点时最多拿了几个数字
首先非负的数字一定要拿,每次拿负数后看一下会不会使当前的值变为负数,否则从之前包括当前位置的负数中选取最负的一个丢弃,可以用优先队列(priority_queue)完成这个操作的维护
注意数据的和会很大,需要用到
long long
#include<bits/stdc++.h>using namespace std;typedef long long ll;int main()
{int n,anss=0;scanf("%d",&n);priority_queue<ll,vector<ll>,greater<ll> >q;ll sum=0;for(int i=0,val;i<n;i++){scanf("%d",&val);if(val>=0){sum+=val;anss++;}else{q.push(val);sum+=val;anss++;if(sum<0){sum-=q.top();anss--;q.pop();}}}cout<<anss<<endl;return 0;
}
D. Kill Anton
Problem - D - Codeforces
题意是给一个只含有
{'A','N','O','T'}
的字串要求求给字串的一个用交换相邻两个字符的操作数最多的排列,值得注意的是这是个可逆的操作,也就是说我们可以从初始串入手经过有效次其实题意就是要相对于原序列的求逆序对最大的序列
先从简单但稍微不那么明显的情况入手(这里说的是有一个重复的字符的情况,如果一个都没有就显而易见的倒序输出就行了)
ANOA→ONAA(orAAONisthesame)ANOA\rarr ONAA\space(or\space AAON\space is\space the\space same)ANOA→ONAA (or AAON is the same),字母太多没看出啥,那就继续,换一个角度,只注意单独一种字符的位置(这里以AAA为例),观察:【x0...xiAxi+1...xjAxj+1...xk→?x_0...x_iAx_{i+1}...x_jAx_{j+1}...x_k\rarr ?x0...xiAxi+1...xjAxj+1...xk→?——①】,不难发现如果移动一个AAA并固定其位置后,都可让其中另一个AAA与这个AAA中间的字符交换(也就是达到俩AAA相邻的情况)会让结果更大,甚至在左边的AAA移动到右边的AAA的右侧时也一样成立。用三个AAA的例子:【x0...xiA1xi+1...xjA2xj+1...xkA3xk+1...xend→?x_0...x_iA_1x_{i+1}...x_jA_2x_{j+1}...x_kA_3x_{k+1}...x_{end}\rarr ?x0...xiA1xi+1...xjA2xj+1...xkA3xk+1...xend→?——②】,在xi+1x_{i+1}xi+1到xendx_{end}xend的子序列就是①的情况,处理完这个子序列,我们将合并的A2A3A_2A_3A2A3看作一个A2A_2A2,剩下的序列又可以看成一个①情况,得到的结果可以再合并。。。这个道理在更多AAA的时候也成立,所以我们可以得到结论:所求的结果一定是相同字符合并在一起的情况
从上面的结论出发,我们可以得到一个算法:全排列
{'A','N','O','T'}
(4!=244!=244!=24种),求出所有情况下需要交换的次数sep(O(n)O(n)O(n)),保留最大的sep对应的排列ord,作为结果输出。时间复杂度为O(24n)→O(n)O(24n)\rarr O(n)O(24n)→O(n)计算这个值的时候只要便利原字符串吧排序在当前字符前的其他字符的数量相加就行,排完这个字符就把这个字符的数量-1从而维护后面的交换次数的计算
其中要注意这个步数可能超过
int
范围!!!
#include<bits/stdc++.h>using namespace std;typedef long long ll;int main()
{int T,n,i,j;ll sep,anss;cin>>T;char str[100007];char ord[5]={'A','N','O','T'},ans_str[5]={'A','N','O','T'};while(T--){scanf("%s",str);n=strlen(str);anss=0;map<char,int>m,mm;for(int i=0;i<n;i++)m[str[i]]++;do{mm=m;sep=0;for(i=0;i<n;i++){for(j=0;ord[j]!=str[i];j++){sep+=mm[ord[j]];}mm[str[i]]--;if(sep>anss){strcpy(ans_str,ord);anss=sep;}}// cout<<sep<<" - ";// mm=m;// for(int i=0;i<4;i++)// {// while(mm[ord[i]]--)// putchar(ord[i]);// }// putchar('\n');}while(next_permutation(ord,ord+4));// cout<<anss<<" - ";for(int i=0;i<4;i++){while(m[ans_str[i]]--)putchar(ans_str[i]);}putchar('\n');}return 0;
}
【Codeforces】Codeforces之丰【部分题解】相关推荐
- Codeforces Round #514 (Div. 2)题解
Codeforces Round #514 (Div. 2)题解 A 喵,直接模拟. B 枚举所有盖章时的,合法的,左上角的位置.能盖的话就盖一下.最后check一下图案是否相等即可 C 一轮一轮的扔 ...
- Codeforces Round #182 (Div. 1)题解【ABCD】
Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...
- 【算法题解】Codeforces Round #817 (Div. 4)题解
文章目录 Codeforces Round #817 (Div. 4)题解 A. Spell Check B. Colourblindness C. Word Game D. Line E. Coun ...
- Codeforces Round #747 (Div. 2)题解
Codeforces Round #747 (Div. 2)题解 (本博客将持续更新以后每场CF div2的题解,喜欢ACM.OI的小伙伴记得点个关注哟) 昨天夜晚刷网络流刷入迷了,渐渐就忘记了我还要 ...
- Codeforces #1248B Grow The Tree题解(Java)
Codeforces #1248B Grow The Tree题解(Java) 题目大意: 输入: 输出: 数据范围: 思路 代码 题目链接 题目大意: 给出一组线段(题目中叫树枝)的长度,制作成一条 ...
- Codeforces Round #789 (Div. 2)题解
Codeforces Round #789 (Div. 2)题解 A. Tokitsukaze and All Zero Sequence 原题链接 算法标签 贪心 排序 思路 情况一:数组存在零 → ...
- Codeforces Round #748 (Div. 3) 题解 完整A~G
Codeforces Round #748 (Div. 3) 题解 A. Elections 题意 已知竞选中三个候选人的当前得票数 a , b , c a,b,c a,b,c,现在可以增加任何一个人 ...
- Codeforces Round #839 (Div. 3)题解
A. A+B? 直接读入字符串然后把下标0和2的数字提取出来就行 // Problem: A. A+B? // Contest: Codeforces - Codeforces Round #839 ...
- Codeforces Round #533 (Div. 2)题解
link orz olinr AK Codeforces Round #533 (Div. 2) 中文水平和英文水平都太渣..翻译不准确见谅 T1.给定n<=1000个整数,你需要钦定一个值t, ...
- Codeforces Round #734 (Div. 3) 题解
Hello大家好,今天给大家带来的是 Codeforces Round #734 (Div. 3) 的全题目讲解. 本文链接:https://www.lanqiao.cn/questions/2040 ...
最新文章
- 将输入字符串t中从第m个字符开始的全部字符复制到字符串s中_leetcode第32双周赛第二题leetcode1540. K 次操作转变字符串...
- R语言观察日志(part4)--paste函数
- flask 上传excel 前端_flask-restful编写上传图片api
- 数据结构基础(14) --链式队列的设计与实现
- java 怎么链接ndk的库_使用ndk-build链接现有的静态库
- Solr查询参数sort(排序)
- Sprite Kit 入门教程
- 表头样式_1分钟学会制作Word两栏、三栏表头
- linux信任本地jar包,jar包在linux本地运行成功, 但是jenkins构建失败
- 论坛指定portal.php,去除Discuz论坛域名后面的/forum.php或portal.php
- 视频教程-CCNA自学视频课程专题四:CCNA认证重点难点解析3(扩展篇)-思科认证
- 信息论基础(考试复习,针对考点)
- Qt结合FFmpeg解码本地视频生成.h264文件和.yuv文件
- CodeGenerator代码生成器使用
- Perl的中国镜像网站--下载速度更快
- linux: It seems that scikit-learn has not been built correctly.
- 麦克马斯特大学计算机的强项,麦克马斯特大学什么专业最好?
- 程序员叫啥名字_他们的名字叫程序员
- 常见的测试用例设计方法7---因果图法
- 一个棋牌游戏的服务端开发1