考虑给定两个M、N串的情况:
定义:两个01串
S,T(|S|≤|T|)
是
coprime
的当且仅当
S=T
。或者如果
S
是
引理1:如果两个串 S,T(|S|≤|T|) 是 coprime 的,则 S+T=T+S
证明:我们对
|T|
进行数学归纳。
当
|T|=1
,则
|S|=1
,由于
S,T
是
coprime
的,则
S=T
,显然
S+T=T+S
,命题成立。
不妨设当
|T|≤k
时命题成立。
当
|T|=k+1
时,若此时
|S|=k+1
,则命题成立。
若
|S|=x<k+1
,则
S
为
则我们要证
S+S+X=S+X+S
,即
S+X=X+S
。由于
S,X
是
coprime
的,所以上式成立,所以当
|T|=k+1
时成立
原命题得证
引理2:若
M≠N
,则
S,T
一定是
coprime
的。
证明方法同上
然后继续分析固定
M
和
如果
M=N
,那么任意一个
01
串都可以。
如果
M≠N
,由于引理1和引理2,我们可以将串
M
和
如果
先考虑
MA>NA,MB<NB
,设
x=MA−NA,y=NB−MB
。现在我们需要让
xS=yT
,令
T=S+X
,显然
x>y
,那么代换后可得
(x−y)S=yX
,不断如此进行下去可以得到
(1,1)
和串
XX
。反观这个过程,我们实际上是
(yXX,xXX)
。所以我们只要找到合法的
XX
即可。
如果
(MA,MB)=(NA,NB)
那么任意一组
coprime
的
S
和
所以我们只需要计算
2gcd(p,q),1≤p,q≤N
假设
cnt[i]
表示的是
i|gcd(p,q)
的
(p,q)
对数,
ans[i]
表示的是
gcd(p,q)=i
的对数,那么
我们总结下前面的推导。
令
dA=MA−NA,dB=MB−NB
如果
dA=dB=0
,则答案为
ans[N]
如果
dA,dB<0
或
dA,dB>0
无解
否则,设
p=|dA|,q=|dB|,d=gcd(p,q)
,那么
ans=2Nmax(p/d,q/d)+1−2
下来考虑问题的原版本
有上述分析可知,对于确定串的方案数如果
M≠N
,仅和
dA
与
dB
相关。所以我们只要能统计出这个的不同方案即可。
假设一开始
M
串
假设
M,N
中分别将
x,y
个问号替换为
A
。那么新的差为
设
d=x−y
,我们只要枚举
d
,并且计算出造成这个
对于一个确定的
d
,我们计算造成这个
在最后我们利用DP考虑下两个串相同的方案数即可。至此,该问题结束。
第一次写这么长的题解,完结撒花!
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<bitset>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
string s;
string t;
int n;
int l1,l2;
LL pow_mod(LL a,LL e)
{
LL res=1;
for (;e;a=a*a%mod,e>>=1) if (e&1) res=res*a%mod;
return res;
}
int miu[610000];
int prim[610000],primm;
bool valid[610000];
void mobius(int N)
{
miu[1]=1;
for (int i=2;i<=N;i++)
{
if (!valid[i]) prim[++primm]=i,miu[i]=-1;
for (int j=1;j<=primm&&i*prim[j]<=N;j++)
{
valid[i*prim[j]]=1;
if (i%prim[j]==0)
{
miu[i*prim[j]]=0;
break;
}
else miu[i*prim[j]]=-miu[i];
}
}
}
LL now;
int na,nb,ma,mb,nn,mm;
LL cnt[310000],ans[310000];
LL res,all;
LL f[610000],ff[610000],inv[610000];
LL C(int n,int m)
{
LL res=(f[n]*inv[m])%mod;
res=(res*inv[n-m])%mod;
return res;
}
LL gcd(LL a,LL b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
mobius(600000);
cin>>s;
cin>>t;
cin>>n;
l1=s.size();
l2=t.size();
if (l1==l2)
{
now=1;
for (int i=0;i<l1;i++)
if (s[i]=='A')
{
if (t[i]=='A'||t[i]=='?');
else now=0;
}
else if (s[i]=='B')
{
if (t[i]=='B'||t[i]=='?');
else now=0;
}
else
{
if (t[i]=='A'||t[i]=='B');
else now=now*2%mod;
}
if (now)
{
LL tmp=(pow_mod(2,n+1)-2+mod)%mod;
tmp=tmp*tmp%mod;
res=tmp*now%mod;
}
}
for (int i=0;i<l1;i++)
if (s[i]=='A') na++;
else if (s[i]=='B') nb++;
else nn++;
for (int i=0;i<l2;i++)
if (t[i]=='A') ma++;
else if (t[i]=='B') mb++;
else mm++;
f[0]=1;
for (int i=1;i<=600010;i++)
f[i]=(f[i-1]*i)%mod;
ff[1]=ff[0]=inv[1]=inv[0]=1;
for (int i=2;i<=600010;i++)
{
inv[i]=(LL)(mod-mod/i)*inv[mod%i]%mod;
ff[i]=inv[i];
}
for (int i=2;i<=600010;i++)
inv[i]=(inv[i-1]*inv[i])%mod;
for (int i=1;i<=n;i++)
cnt[i]=LL(n/i)*(LL)(n/i);
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n/i;j++)
ans[i]+=(LL)miu[j]*cnt[i*j];
all+=ans[i]*pow_mod(2,i);
all%=mod;
}
int p=na-ma,q=nb-mb+(nn-mm);
for (int i=-mm;i<=nn;i++)
{
LL tmp=C(nn+mm,mm+i);
int np=p+i,nq=q-i;
if (np==0&&nq==0) tmp=(tmp-now+mod)%mod;
if (np==nq&&np==0) res=(res+tmp*all)%mod;
else if (np<=0&&nq<=0||np>=0&&nq>=0);
else
{
int d=gcd(np,nq);
np/=d,nq/=d;
tmp=tmp*(pow_mod(2,n/max(abs(np),abs(nq))+1)-2+mod)%mod;
res=(res+tmp)%mod;
}
}
cout<<res<<endl;
return 0;
}