codeforce div2 b Infinite Prefixes详解

题目如图
codeforce div2 b Infinite Prefixes详解_第1张图片
题目表达的很复杂,看了很久都不能理解一堆abc的例子在表达什么,在别人帮助翻译后大致理解了题意
其实简单来说就是给一个长度已知可以无限重复的字符串,只有0和1两种字符,问有几个点可以使0比1多x个,比如样例1,
010010 1个子串0比1多2个,所以前四个子串结束后0一共比1多了8个,而0比1多10个将在下一个子串中出现,也就是28 30 和32
需要注意的还有如果要求为0,则需要考虑空前缀的问题
那么开始设计程序,我们必须考虑所有情况,但因为字符穿无限,我们不能直接全部搜索,于是我们把问题先分解成两种情况,及子串中0和1个数相同或不同,先讨论相同的情况,如果0和1相同,就意味着次数的累计不能帮助0比1多的个数增加。所以遍历一遍子串,看其中有没有可以使0比1多x的点,如果有则后续一定有无限个,输出-1,如果没有就永远不会出现这个点,输出0.
再看第二种情况,如果在一个子串完结后0比1多了T个,那么在一次次的累计种,0比1多的会越来越多,解一点是有限个甚至0个,但是我们不能确定解的具体位置,那么想一想答案出现的点会有的特征,不难发现,这个点一定是在某一个子串中的某一个位置出现的,所以我们还是只用遍历一个子串用d记录当前0比1多的次数,至于如何确定答案,我认为T的某个倍数加目前此次遍历过程中0比1多的次数等于x的点就是答案存在的点,翻译成程序就是(x-d)%T==0与此同时我们还要保证此时(x-d)应该和T同号,否则随着子串的延长,会离答案越来越远,

想好了思路代码自然就可以顺利的出`

#include
using namespace std;
char a[1000]
int main()
{
int n,q,d,x,T,ans;
cin<<n;
while(n--)
{
ans=0;T=0;d=0;
(int i=1;i<=1000;i++)
a[i]='0';//数组初始化
scanf("%d%d",&q,&x)
scanf("%s",a+1)for(int i=1;i<=q;i++)
{
if(a[i]=='0')T++;
else T--;
}
if(x==0)ans++;
if(T==0)
   {
for(int i=1;i<=q;i++)
{
if(a[i]=='0')d++;
else d--;
if(d==x)ans=-1;
}
   }
else
   {
    for(int i=1;i<=q;i++)
{
if(a[i]=='0')d++;
else d--;
if((x-d)%T==0&&(x-d)/T>=0)ans++;
}
   }
   printf("%d\n",ans);
return 0;
}

主要注意几个坑,考虑x==0是存在空前缀的情况
注意在每一遍的过程一定可以找到所有符合答案的情况。

tnl

你可能感兴趣的:(codeforce)