题解:CF794G Replace All
Union_of_Britain · · 题解
追赶 hanghang 的脚步!!其实不是非常困难。
考虑一个
进一步的,目前前缀被替换成了
这不是更相减损术吗?最后直到
显然,无限制当且仅当原串全同。而有限制时一个单位任取,因此非全同的方案数就是
然后设
然后设第一、二串选了
这只跟
计算
这是容易数论分块套数论分块
最后全同处理一下就可以了。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=6e5+5,mod=1e9+7;
int n,m,lim,fac[maxn],ifac[maxn],A,B,C,a,b,c,N=6e5,t[maxn],dt=3e5,pw[maxn];
int Bi(int a,int b){
if(b>a||b<0)return 0;
return fac[a]*ifac[b]%mod*ifac[a-b]%mod;
}
int qp(int a,int b){
if(b==0)return 1;
int T=qp(a,b>>1);T=T*T%mod;
if(b&1)T=T*a%mod;
return T;
}
string S,T;
int sig(int x){return (x>0)-(x<0);}
int S2(int x){return pw[x+1]-1;}
int mu[maxn],isp[maxn];
vector<int> pr;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
fac[0]=1;for(int i=1;i<=N;i++)fac[i]=fac[i-1]*i%mod;
ifac[N]=qp(fac[N],mod-2);
for(int i=N-1;i>=0;i--)ifac[i]=ifac[i+1]*(i+1)%mod;
pw[0]=1;for(int i=1;i<=N;i++)pw[i]=pw[i-1]*2%mod;
mu[1]=1;
for(int i=2;i<=N;i++){
if(!isp[i])pr.push_back(i),mu[i]=-1;
for(auto u:pr){
if(i*u>N)break;
isp[i*u]=1;
if(i%u==0){mu[i*u]=0;break;}
mu[i*u]=mu[i]*mu[u];
}
}
cin>>S>>T;n=S.length();m=T.length();cin>>lim;
for(int i=0;i<n;i++)a+=(S[i]=='A'),b+=(S[i]=='B'),c+=(S[i]=='?');
for(int i=0;i<m;i++)A+=(T[i]=='A'),B+=(T[i]=='B'),C+=(T[i]=='?');
for(int i=-C;i<=c;i++)t[i+dt]=Bi(c+C,C+i);
int ans=0,qsy=0;
for(int l=1,r;l<=lim;l=r+1){
r=lim/(lim/l);
int res=0;
for(int j=1;j<=lim/l;j++)(res+=mu[j]*((lim/l)/j)%mod*((lim/l)/j))%=mod;
(qsy+=res*(S2(r)-S2(l-1)+mod)%mod)%=mod;
}
// for(int i=1;i<=lim;i++)for(int j=1;j<=lim;j++)(qsy+=pw[__gcd(i,j)])%=mod;
for(int i=-C;i<=c;i++){
int c1=a-A+i,c2=B+C-b-c+i;
if(sig(c1)!=sig(c2))continue;
// cout<<i<<" "<<c1<<" "<<c2<<" "<<t[i+dt]<<endl;
if(sig(c1)==1){
if(c1<c2)swap(c1,c2);
(ans+=(pw[lim/(c1/__gcd(c1,c2))+1]-2)*t[dt+i])%=mod;
}else if(sig(c1)==-1){
c1=-c1,c2=-c2;
if(c1<c2)swap(c1,c2);
(ans+=(pw[lim/(c1/__gcd(c1,c2))+1]-2)*t[dt+i])%=mod;
}else{
(ans+=qsy*t[dt+i])%=mod;
}
}
if(n==m){
bool flg=1;int cnt=0;
for(int i=1;i<=n;i++){
if(S[i-1]!='?'&&S[i-1]!=T[i-1]&&T[i-1]!='?'){flg=0;break;}
if(S[i-1]==T[i-1]&&S[i-1]=='?')++cnt;
}
if(flg){
(ans+=((pw[lim+1]-2)*(pw[lim+1]-2)%mod+mod-qsy)*pw[cnt])%=mod;
}
}
cout<<ans<<endl;
return 0;
}