前言
看错题,这题我做了2.5h…
题目大意
给你一个形如ss的小写字母字符串,即两个一样的字符串拼接。
然后定义一个函数f,f(ss)表示一个字符串,他形如ss+t,然后f(ss)也要能够写成s1s1的形式。
问调用f 10^100次后,得到的字符串的s[l..r]中,a..z各出现多少次。
l,r<=1e18,|s|<2e5
解题思路
首先打表找一下规律…发现每次调用,要么字符串增加一段相等的东西,要不就像斐波那契数列一样增加。
我们来分析一下调用一次会发生什么。
考虑SS=s[1]…s[n]s[1]…s[n]。那么我们肯定要在后面增加2k个字符,那么变成s[1]…s[n]s[1]…[k] s[k+1]…s[n]T[1]…T[2k],其中T是新加入的字符。先不管T是什么,我们可以直接发现s有个k的周期。那么后面的T你直接对应一下即可。
那么我们发现f(SS)=STST,其中T为s[1..k],k为s最短周期。
这样我们直接分析一个S即可。设g(s)=st,也就是f的一半。
根据我们打表,加一点分析:
1,若一开始k整除|S|,那么
g+∞(s)=stttttt...
g
+
∞
(
s
)
=
s
t
t
t
t
t
t
.
.
.
2,其他情况,g(s)=st,g(st)=sts…
gi(s)=gi−1(s)+gi−2(s)
g
i
(
s
)
=
g
i
−
1
(
s
)
+
g
i
−
2
(
s
)
那么我们通过这个可以直接计算次数了。因为第二种情况不用100次长度就爆掉1e18了。
注意到1和2的情况可以一起搞,由于长度很大我们直接用g跑。一开始用f跑不知道干嘛错了。
怎么证明这两个性质呢?我们证明2就好,1的话很好搞。
设s=t*n+t’,其中t’是t的一个前缀且t’≠t,t是s的最短周期。我们想要证明g(s)=t*n+t’+t的最短周期是|t|*n+|t’|。
假设存在周期x<|t|*n+|t’|。
情况1:x mod |t|≠ |t’|,那么t必然有另一个周期gcd(|T|,x-|T|),画画就知道,那么S也有这个周期,那么t就不是s的最短周期。矛盾
情况2: x mod |t|=|t’|,这种情况也类似。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define fo(i,j,k) for(i=j;i<=k;i++)
#define fd(i,j,k) for(i=j;i>=k;i--)
#define cmax(a,b) (a=(a>b)?a:b)
#define cmin(a,b) (a=(a<b)?a:b)
typedef long long ll;
const int N=2e6+5,M=1e7+50,mo=1e9+7;
int fail[N],n,i,per;
ll len1,len2,d,prt[30],l,r,f[305][26],g[305][26],sf[305],sg[305];
char s[N];
void kmp()
{
int i,j;
j=0;
n=strlen(s+1)/2;
fo(i,2,n)
{
while (j&&s[i]!=s[j+1]) j=fail[j];
if (s[i]==s[j+1]) j++;
fail[i]=j;
}
}
void fib()
{
int i,j;
fo(i,2,300)
{
fo(j,0,25) g[i][j]=g[i-1][j]+g[i-2][j];
sg[i]=sg[i-1]+sg[i-2];
if (sg[i]*2>r) break;
}
fo(i,0,300)
{
fo(j,0,25) f[i][j]=g[i][j]*2;
sf[i]=sg[i]*2;
if (sf[i]>r) break;
}
}
void calc(ll x,ll xs)
{
int pos;
fo(pos,0,300)
if (sg[pos]>x) break;
while (pos>=0)
{
if (sg[pos]<=x)
{
fo(i,0,25) prt[i]+=xs*g[pos][i];
x-=sg[pos];
pos--;
}else
pos--;
}
fo(i,1,x) prt[s[i]-'a']+=xs;
}
int main()
{
freopen("t20.in","r",stdin);
freopen("t20.out","w",stdout);
scanf("%s %lld %lld",s+1,&l,&r);
kmp();
fo(i,1,n) g[0][s[i]-'a']++,sg[0]++;
per=n-fail[n];
fo(i,0,25) g[1][i]=g[0][i];
sg[1]=sg[0];
fo(i,1,per) g[1][s[i]-'a']++,sg[1]++;
fib();
calc(r,1);
calc(l-1,-1);
fo(i,0,25) printf("%lld ",prt[i]);
}