联考 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);
}

posted @ 2020-05-25 16:06  Izayoi_Doyo  阅读(191)  评论(0编辑  收藏  举报