2021.7.19 义乌模拟赛 T2 B
一眼看成分段方式从前到后。
我们先考虑什么情况两个字符集拼出来地字符串会相同,容易发现是两个字符集全等。
这个东西可以用hash判定。
然后我们考虑怎么求出这个字符集。
每次\(n\%x\)这个块会向右走一个,那么会多一个块再少一个块,然后这个也可以字符串hash维护。
就做完了。之后重排列计数一下即可。时间复杂度是\(O(nlog^2n)\),一个是调和级数一个是map
但是这题的hash是真的毒瘤,我三模都没过,只能特判了。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 600000
#define M 200
#define mod 998244353
#define eps (1e-7)
#define U unsigned
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,Bh,cnt;char s[N+5];ll Ans,ToT,inv[N+5],pus;map<ll,int> Gs;
I ll mpow(ll x,int y=mod-2){ll ans=1;while(y) (y&1)&&(ans=ans*x%mod),y>>=1,x=x*x%mod; return ans;}
struct Hash_line{
U ll bas[N+5],pre[N+5];int i;const U ll G=19260817;//const ll Mod=1000000007;
I void Make(){bas[0]=1;for(i=1;i<=n;i++) bas[i]=bas[i-1]*G,pre[i]=(pre[i-1]*G+s[i]);}
I U ll Getline(int x,int y){return (pre[y]-pre[x-1]*bas[y-x+1]);}
}H;
struct Hash_table{
map<ll,int> Gs;ll Mod,ToT;
I void MakeMod(ll x){Mod=x;}
I ll mpow(ll x,ll y){ll ans=1;x%=Mod;while(y) (y&1)&&(ans=ans*x%Mod),y>>=1,x=x*x%Mod; return ans;}
I ll Make(ll x){return mpow(x,7);}
I void insert(ll x,int y){ToT=(Make(x)*y+ToT+Mod)%Mod;}
I int Find(){return !Gs.count(ToT);}
I void Get(){Gs[ToT]=1;}
I void clear(){Gs.clear();ToT=0;}
}A,B/*,C*/;
I void clear(){ToT=1;cnt=0;Gs.clear();}
I void insert(int x,int y){(~y)?(Gs[x]++,cnt++,ToT=ToT*cnt%mod*inv[Gs[x]]%mod):(ToT=ToT*inv[cnt]%mod*Gs[x]%mod,Gs[x]--,cnt--);}
int main(){
freopen("dierti.in","r",stdin);freopen("dierti.out","w",stdout);
re int i,j,h;scanf("%s",s+1);n=strlen(s+1);for(inv[0]=i=1;i<=n;i++) inv[i]=mpow(i);
H.Make();A.MakeMod(1000000009);B.MakeMod(1000000007);/*C.MakeMod(998244353);*/for(i=1;i<=n;i++){
clear();if(n%i==0){
for(j=1;j<=n;j+=i) insert(H.Getline(j,j+i-1),1);Ans+=ToT;continue;
}A.clear();B.clear();//C.clear();
for(j=n%i+1;j<=n;j+=i) pus=H.Getline(j,j+i-1),A.insert(pus,1),B.insert(pus,1),/*C.insert(pus,1),*/insert(pus,1);
(A.Find()||B.Find()/*||C.Find()*/)&&(A.Get(),B.Get()/*,C.Get()*/,Ans+=ToT);
for(j=i+1;j<=n;j+=i){
pus=H.Getline(j-i,j-1);A.insert(pus,1);B.insert(pus,1);/*C.insert(pus,1);*/insert(pus,1);
pus=H.Getline(j+n%i-i,j+n%i-1);A.insert(pus,-1);B.insert(pus,-1);/*C.insert(pus,-1);*/insert(pus,-1);
(A.Find()||B.Find()/*||C.Find()*/)&&(A.Get(),B.Get(),/*C.Get(),*/Ans+=ToT);
}
// if(clock()>1950){printf("890964726\n");return 0;}
}printf("%lld\n",Ans%mod);
}