【CF#526D/51nod1554】欧姆诺姆和项链
这道题非常玄妙啊
首先我们把$S$拆成循环串,即$S=PPPPPPPPT$,其中$T$是$P$的前缀
设$S$中含有$R$个$T$,因为$S=A+B+…+B+A$,所以设$A$中含有$x$个$T$,则AB中含有$\frac{R-x}{k}$个T,且$k|(R-x)$
所以B中含有$\frac{R-x}{k}-x$ 个T,我们需要满足$x>=0$的同时使得$\frac{R-x}{k}-x>0$
设$f(x)= \frac{R-x}{k}-x$,我们要保证$f(x)>0$,也就是说保证$f(x)$的最大值大于$0$
我们发现$f(x)$为减函数,所以$x$的取值应该尽量小,同时又要满足$k|(R-x)$,所以$x=R\%k$
所以我们只需要令$x=R\%k$,然后判断$f(x)$是否大于$0$即可
特别的如果$P=T$,那么$B$串是可以为空的,也就是说保证的是$f(x)>=0$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include<bits/stdc++.h> #define FILE "read" #define MAXN 1000010 using namespace std; int n,k,pre[MAXN]; char ch[MAXN]; inline int read(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } int main(){ freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); n=read(); k=read(); scanf("%s",ch+1); pre[1]=0; for(int i=2,j=0;i<=n;++i){ while(ch[j+1]!=ch[i]&&j) j=pre[j]; if(ch[j+1]==ch[i]) ++j; pre[i]=j; } for(int i=1;i<=n;++i){ int R=i/(i-pre[i]); if(i%(i-pre[i])){ if(R/k-R%k>0) putchar('1'); else putchar('0'); } else{ if(R/k-R%k>=0) putchar('1'); else putchar('0'); } } return 0; }
|