联考 20200523 T2 蓝超巨星
分析:
(一道破题调一天)
我们把A操作和B操作分开考虑
不看字符的变化,A操作会产生\(N=n/gcd(n,a)\)种字符串
不看字符的位移,B操作会产生\(M\)种字符串
其中\(M\)为所有字符通过操作形成的种类数,最坏情况为\(M=4*9*5*7=1260\)
枚举种类\(q(0 \leq q < M)\),哈希判断字符串的位移次数\(p\)
(复杂度是\(O(NM)\)的,应该不是那么容易卡掉
那么设最终操作次数为\(x\)
列出同余方程:
\(x \equiv p(mod N)\)
\(x \equiv q(mod M)\)
于是开始解方程,一定注意这里是不互质的!
\(x=Nx_1+p=Mx_2+q~~~~~~~~~~(1)\)
\(Nx_1 \equiv q-p(mod M)\)
令\(d=gcd(N,M)\),所以:
\(\frac{N}{d}x_1 \equiv \frac{q-p}{d}(mod \frac{M}{d})\)
令\(X=\frac{c}{d}(\frac{N}{d})^{-1}\)
\(x_1 \equiv X(mod \frac{M}{d})\)
\(x_1=\frac{M}{d}y+X\)
将(1)式代入:
\(x=\frac{NM}{d}y+NX+p\)
\(x \equiv NX+p(mod \frac{NM}{d})\)
代码就实现这个过程就好了
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<string>
#define maxn 400005
#define INF 0x3f3f3f3f
#define base 29
using namespace std;
inline long long getint()
{
long long num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
}
int n,m=1,A,B;
char s[maxn],t[maxn];
int a[maxn],b[maxn],c[maxn],sz[maxn];
int S[maxn],T[maxn];
long long HS,hs[maxn],pw=1;
long long ans=-1;
inline int gcd(int p,int q)
{return q?gcd(q,p%q):p;}
inline int lcm(int p,int q)
{return p*q/gcd(p,q);}
inline long long exgcd(long long p,long long q,long long &x,long long &y)
{
if(!q){x=1,y=0;return p;}
long long num=exgcd(q,p%q,x,y);
long long t=x;x=y,y=t-p/q*y;
return num;
}
inline long long getans(long long p,long long q)
{
long long N=n/gcd(n,A),M=m;
long long d=gcd(N,M),c=q-p,k1,k2;
exgcd(N,M,k1,k2);
if(c%d)return -1;
long long X=c/d*k1,t=M/d;
X=(X%t+t)%t;
X=p+N*X;
if(X<=0)X+=lcm(N,M);
return X;
}
inline void solve(int num)
{
for(int i=1;i<=n;i++)S[i+n]=S[i];
for(int i=1;i<=2*n;i++)hs[i]=hs[i-1]*base+S[i];
int blk=gcd(n,A);
for(int i=n;i<2*n;i+=blk)
if(hs[i]-hs[i-n]*pw==HS)
{
long long tmp=getans(a[i%n],num);
if(!~ans||(tmp!=-1&&tmp<ans))ans=tmp;
}
}
int main()
{
//freopen("blue.in","r",stdin);
//freopen("blue.out","w",stdout);
n=getint(),A=getint()%n,B=getint();
for(int i=1,now=A;now;i++,now=(now+A)%n)a[now]=i;
scanf("%s",s+1);
for(int i=1;i<=26;i++)b[i]=s[i]-96;
for(int i=1;i<=26;i++){int tmp=i;do{tmp=b[tmp],sz[i]++;}while(tmp!=i);}
for(int i=1;i<=26;i++)
{
int tmp=B%sz[i],x=i;
while(tmp--)x=b[x];c[i]=x;
}
for(int i=1;i<=26;i++)b[i]=c[i],sz[i]=0;
for(int i=1;i<=26;i++){int tmp=i;do{tmp=b[tmp],sz[i]++;}while(tmp!=i);}
for(int i=1;i<=26;i++)m=lcm(m,sz[i]);
scanf("%s",s+1);
for(int i=1;i<=n;i++)S[i]=s[i]-96,pw=pw*base;
scanf("%s",t+1);
for(int i=1;i<=n;i++)T[i]=t[i]-96,HS=HS*base+T[i];
for(int t=0;t<m;t++)
{
solve(t);
for(int i=1;i<=n;i++)S[i]=b[S[i]];
}
printf("%lld\n",ans);
}