题解 蓝超巨星

传送门

发现可以矩阵快速幂预处理出一次递进的字符集映射
发现然后需要知道的就是要递进多少次才能变成 \(t\)
考虑那个映射的周期是 \(\mathrm{lcm}\),大约是 \(1260\) 级别的,可以接受
但是再考虑那个循环移位周期就大了去了(
那么忽略循环移位,只跑不加循环移位的递进,若某次与 \(t\) 循环同构
则根据现在应该移多少位可以列出一个 \(\pmod n\) 的和一个 \(\pmod{\mathrm{lcm}}\) 的同余方程
解出来就可以了
复杂度貌似较高,但可以通过所有数据

一个比较靠谱的做法:
枚举最终移位了多少位
通过集合 hash \((i-lst_i)*base^i\)(其中 \(lst_i\) 为上一个与 \(i\) 同类型的元素的位置)
可以知道是否可以通过对字符集进行一些变换使得当前移位过的 \(s=t\)
然后又知道了每个字符对应应该变成什么
那么可以再列出 \(26\) 个同余方程,解就行了
\(base\)\(mod\) 互质可以利用逆元
复杂度 \(O(26^2n)\)

  • 集合 hash(等价类 hash?)
    可以利用 \((i-lst_i)*base^i\)(其中 \(lst_i\) 为上一个与 \(i\) 同类型的元素的位置)对等价类进行一个 hash
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define N 400010
#define fir first
#define sec second
#define ll long long
#define ull unsigned long long
//#define int long long

int n, a, b;
char f[N], s[N], t[N];

namespace force{
	char tem[N];
	void once() {
		for (int i=0; i<n; ++i) tem[((i-a)%26+26)%26]=s[i];
		for (int i=0; i<n; ++i) s[i]=tem[i];
		for (int i=0; i<n; ++i)
			for (int j=1; j<=b; ++j)
				s[i]=f[s[i]-'a'];
	}
	void solve() {

	}
}

namespace task1{
	struct matrix{
		int n, m;
		int a[26][26];
		matrix() {n=m=0; memset(a, 0, sizeof(a));}
		matrix(int x, int y) {n=x; m=y; memset(a, 0, sizeof(a));}
		void resize(int x, int y) {n=x; m=y; memset(a, 0, sizeof(a));}
		inline int* operator [] (int t) {return a[t];}
		inline void put() {for (int i=0; i<n; ++i) {for (int j=0; j<m; ++j) cout<<a[i][j]<<' '; cout<<endl;}cout<<endl;}
		inline matrix operator * (matrix b) {
			matrix ans(n, b.m);
			for (int i=0; i<n; ++i)
				for (int k=0; k<m; ++k) if (a[i][k])
					for (int j=0; j<b.m; ++j) if (b[k][j])
						ans[i][j]+=a[i][k]*b[k][j];
			return ans;
		}
	}mat, tr, I;
	ll ans=INF;
	ull h[N], pw[N];
	char g[N], tem[N];
	int dsu[N], siz[N];
	const ull base=13131;
	inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
	inline void uni(int s, int t) {if ((s=find(s))!=(t=find(t))) siz[dsu[s]=t]+=siz[s];}
	inline int gcd(int a, int b) {return !b?a:gcd(b, a%b);}
	inline int lcm(int a, int b) {return a/gcd(a, b)*b;}
	inline ull hashing(int l, int r) {return h[r]-h[l-1]*pw[r-l+1];}
	inline matrix qpow(matrix a, ll b) {matrix ans=I; for (; b; a=a*a,b>>=1) if (b&1) ans=ans*a; return ans;}
	void exgcd(ll a, ll b, ll& x, ll& y) {
		if (!b) {x=1; y=0; return ;}
		exgcd(b, a%b, y, x);
		y-=a/b*x;
	}
	ll excrt(vector<pair<ll, ll>> sta) {
		ll rest=sta[0].fir, lcm=sta[0].sec;
		ll x1, x2, g=gcd(lcm, sta[1].sec);
		exgcd(lcm, sta[1].sec, x1, x2);
		if ((sta[1].fir-rest)%g) return INF;
		x1=x1*((sta[1].fir-rest)/g);
		rest=rest+x1*lcm;
		lcm=lcm/gcd(lcm, sta[1].sec)*sta[1].sec;
		rest=(rest%lcm+lcm)%lcm;
		return rest;
	}
	void force_solve() {
		for (int ans=1; clock()<900000; ++ans) {
			for (int i=0; i<n; ++i) tem[((i-a)%n+n)%n]=s[i];
			for (int i=0; i<n; ++i) s[i]=tem[i];
			for (int i=0; i<n; ++i) s[i]=g[tem[i]];
			// for (int i=0; i<n; ++i)
			// 	for (int j=1; j<=b; ++j)
			// 		s[i]=f[s[i]]-'a';
			// cout<<"s: "; for (int i=0; i<n; ++i) cout<<(char)(s[i]+'a')<<' '; cout<<endl;
			for (int i=0; i<n; ++i) if (s[i]!=t[i]) goto jump;
			printf("%d\n", ans); exit(0);
			jump: ;
		}
		puts("-1"); exit(0);
	}
	void solve() {
		I.resize(26, 26);
		for (int i=0; i<26; ++i) I[i][i]=1;
		tr.resize(26, 26);
		for (int i=0; i<26; ++i) tr[i][f[i]-'a']=1;
		mat.resize(1, 26);
		for (int i=0; i<26; ++i) mat[0][i]=i;
		mat=mat*qpow(tr, b);
		for (int i=0; i<26; ++i) g[mat[0][i]]=i;
		// a%=26;
		for (int i=0; i<n; ++i) s[i]-='a', t[i]-='a';
		for (int i=0; i<26; ++i) siz[dsu[i]=i]=1;
		for (int i=0; i<26; ++i) uni(i, g[i]);
		int T=1;
		for (int i=0; i<26; ++i) if (find(i)==i) T=lcm(T, siz[i]);
		// cout<<"T: "<<T<<endl;
		pw[0]=1;
		for (int i=1; i<=2*n; ++i) pw[i]=pw[i-1]*base;
		ull tem=0;
		for (int i=0; i<n; ++i) tem=tem*base+t[i];
		// if (n<=300) force_solve();
		ll tlcm=lcm(n, T);
		for (int i=1; i<=T; ++i) {
			for (int j=0; j<n; ++j) s[j]=g[s[j]];
			// cout<<"s: "; for (int i=0; i<n; ++i) cout<<(char)(s[i]+'a')<<' '; cout<<endl;
			for (int j=1; j<=n; ++j) h[j]=h[j-1]*base+s[j-1];
			for (int j=n+1; j<=2*n; ++j) h[j]=h[j-1]*base+s[j-n-1];
			for (int j=1; j<=n; ++j) if (hashing(j, j+n-1)==tem) {
				// cout<<"ij: "<<i<<' '<<j<<endl;
				// cout<<"s: "; for (int i=0; i<n; ++i) cout<<(char)(s[i]+'a')<<' '; cout<<endl;
				int need=j-1;
				// cout<<"need: "<<need<<endl;
				for (int now=0; now<n; ++now) if (1ll*a*now%n==need) {
					// cout<<now<<' '<<n<<','<<i<<' '<<T<<endl;
					ll tem=excrt({{now, n}, {i, T}});
					// cout<<"tem: "<<tem<<endl;
					ans=min(ans, tem?tem:tlcm);
				}
			}
		}
		printf("%lld\n", ans==INF?-1ll:ans);
	}
}

signed main()
{
	freopen("blue.in", "r", stdin);
	freopen("blue.out", "w", stdout);

	scanf("%d%d%d", &n, &a, &b);
	scanf("%s%s%s", f, s, t);
	// force::solve();
	task1::solve();

	return 0;
}
posted @ 2022-06-13 17:26  Administrator-09  阅读(3)  评论(0编辑  收藏  举报