#include <bits/stdc++.h> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef vector<int> VI; typedef long long ll; typedef pair<int,int> PII; typedef double db; mt19937 mrand(233333); int rnd(int x) { return mrand() % x;} const ll mod=1000000007; ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;} // head typedef int i32; typedef unsigned int u32; typedef long long i64; typedef unsigned long long u64; struct Mod32 { Mod32():n_(0) {} Mod32(u32 n):n_(init(n)) {} static u32 init(u32 w) { return reduce(u64(w) * r2); } static void set_mod(u32 m) { mod=m; assert(mod&1); inv=m; rep(i,0,4) inv*=2-inv*m; r2=-u64(m)%m; } static u32 reduce(u64 x) { u32 y=u32(x>>32)-u32((u64(u32(x)*inv)*mod)>>32); return i32(y)<0?y+mod:y; } Mod32& operator += (Mod32 rhs) { n_+=rhs.n_-mod; if (i32(n_)<0) n_+=mod; return *this; } Mod32 operator + (Mod32 rhs) const { return Mod32(*this)+=rhs; } Mod32& operator -= (Mod32 rhs) { n_-=rhs.n_; if (i32(n_)<0) n_+=mod; return *this; } Mod32 operator - (Mod32 rhs) const { return Mod32(*this)-=rhs; } Mod32& operator *= (Mod32 rhs) { n_=reduce(u64(n_)*rhs.n_); return *this; } Mod32 operator * (Mod32 rhs) const { return Mod32(*this)*=rhs; } u32 get() const { return reduce(n_); } static u32 mod,inv,r2; u32 n_; }; u32 Mod32::mod,Mod32::inv,Mod32::r2; Mod32 zero; const int N=10100; Mod32 fac[N],fnv[N]; int r[10],n; char s[10][N]; Mod32 comb(int x,int y) { if (y<0||y>x) return zero; else return fac[x]*fnv[y]*fnv[x-y]; } Mod32 calc(int x) { Mod32 ans=zero; for (int i=0;i<=x;i++) ans+=comb(n,i); return ans; } Mod32 qs[N],sq[N]; Mod32 calc(int x1,int x2,char *s1,char *s2) { int c1=0,c2=0; rep(i,0,n) if (s1[i]==s2[i]) c1++; else c2++; sq[0]=zero; Mod32 ans=zero; x2-=c2; for (int p=0;p<=c1;p++) sq[p+1]=sq[p]+comb(c1,p); for (int q=0;q<=c2;q++) { int fp=min(x1-q,x2+q); fp=min(fp,c1); if (fp>=0) ans+=comb(c2,q)*sq[fp+1]; } return ans; } Mod32 calc(int x1,int x2,int x3,char *s1,char *s2,char *s3) { static int c[10]; rep(i,0,4) c[i]=0; rep(i,0,n) { c[(s1[i]!=s2[i])*2+(s1[i]!=s3[i])]++; } Mod32 ans=zero; x3=x3-c[1]-c[3]; x2=x2-c[2]-c[3]; int rs=-c[3]; for (int pq=c[0];pq>=-c[1];pq--) { while (pq+rs<=x3&&rs<=c[2]) { for (int s=max(0,-rs);s<=c[3]&&s+rs<=c[2];s++) { int r=s+rs; assert(r>=0&&r<=c[2]); qs[r+s]+=comb(c[2],r)*comb(c[3],s); } rs++; } sq[0]=zero; for (int i=0;i<=c[2]+c[3];i++) sq[i+1]=sq[i]+qs[i]; for (int q=max(0,-pq);q<=c[1]&&q+pq<=c[0];q++) { int p=q+pq; int fr=x1-p-q,fl=p+q-x2; fl=max(fl,0); fr=min(fr,c[2]+c[3]); if (fl<=fr) ans+=comb(c[0],p)*comb(c[1],q)*(sq[fr+1]-sq[fl]); } } return ans; } int main() { Mod32::set_mod(mod); scanf("%d",&n); fac[0]=1u; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*(u32)i; for (int i=0;i<=n;i++) fnv[i]=(u32)powmod(fac[i].get(),mod-2); rep(i,0,3) { scanf("%d%s",r+i,s[i]); } Mod32 ans=calc(r[0])+calc(r[1])+calc(r[2]); ans=ans-calc(r[0],r[1],s[0],s[1])-calc(r[0],r[2],s[0],s[2])-calc(r[1],r[2],s[1],s[2]); ans+=calc(r[0],r[1],r[2],s[0],s[1],s[2]); printf("%d\n",(int)ans.get()); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | #include <bits/stdc++.h> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef vector<int> VI; typedef long long ll; typedef pair<int,int> PII; typedef double db; mt19937 mrand(233333); int rnd(int x) { return mrand() % x;} const ll mod=1000000007; ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;} // head typedef int i32; typedef unsigned int u32; typedef long long i64; typedef unsigned long long u64; struct Mod32 { Mod32():n_(0) {} Mod32(u32 n):n_(init(n)) {} static u32 init(u32 w) { return reduce(u64(w) * r2); } static void set_mod(u32 m) { mod=m; assert(mod&1); inv=m; rep(i,0,4) inv*=2-inv*m; r2=-u64(m)%m; } static u32 reduce(u64 x) { u32 y=u32(x>>32)-u32((u64(u32(x)*inv)*mod)>>32); return i32(y)<0?y+mod:y; } Mod32& operator += (Mod32 rhs) { n_+=rhs.n_-mod; if (i32(n_)<0) n_+=mod; return *this; } Mod32 operator + (Mod32 rhs) const { return Mod32(*this)+=rhs; } Mod32& operator -= (Mod32 rhs) { n_-=rhs.n_; if (i32(n_)<0) n_+=mod; return *this; } Mod32 operator - (Mod32 rhs) const { return Mod32(*this)-=rhs; } Mod32& operator *= (Mod32 rhs) { n_=reduce(u64(n_)*rhs.n_); return *this; } Mod32 operator * (Mod32 rhs) const { return Mod32(*this)*=rhs; } u32 get() const { return reduce(n_); } static u32 mod,inv,r2; u32 n_; }; u32 Mod32::mod,Mod32::inv,Mod32::r2; Mod32 zero; const int N=10100; Mod32 fac[N],fnv[N]; int r[10],n; char s[10][N]; Mod32 comb(int x,int y) { if (y<0||y>x) return zero; else return fac[x]*fnv[y]*fnv[x-y]; } Mod32 calc(int x) { Mod32 ans=zero; for (int i=0;i<=x;i++) ans+=comb(n,i); return ans; } Mod32 qs[N],sq[N]; Mod32 calc(int x1,int x2,char *s1,char *s2) { int c1=0,c2=0; rep(i,0,n) if (s1[i]==s2[i]) c1++; else c2++; sq[0]=zero; Mod32 ans=zero; x2-=c2; for (int p=0;p<=c1;p++) sq[p+1]=sq[p]+comb(c1,p); for (int q=0;q<=c2;q++) { int fp=min(x1-q,x2+q); fp=min(fp,c1); if (fp>=0) ans+=comb(c2,q)*sq[fp+1]; } return ans; } Mod32 calc(int x1,int x2,int x3,char *s1,char *s2,char *s3) { static int c[10]; rep(i,0,4) c[i]=0; rep(i,0,n) { c[(s1[i]!=s2[i])*2+(s1[i]!=s3[i])]++; } Mod32 ans=zero; x3=x3-c[1]-c[3]; x2=x2-c[2]-c[3]; int rs=-c[3]; for (int pq=c[0];pq>=-c[1];pq--) { while (pq+rs<=x3&&rs<=c[2]) { for (int s=max(0,-rs);s<=c[3]&&s+rs<=c[2];s++) { int r=s+rs; assert(r>=0&&r<=c[2]); qs[r+s]+=comb(c[2],r)*comb(c[3],s); } rs++; } sq[0]=zero; for (int i=0;i<=c[2]+c[3];i++) sq[i+1]=sq[i]+qs[i]; for (int q=max(0,-pq);q<=c[1]&&q+pq<=c[0];q++) { int p=q+pq; int fr=x1-p-q,fl=p+q-x2; fl=max(fl,0); fr=min(fr,c[2]+c[3]); if (fl<=fr) ans+=comb(c[0],p)*comb(c[1],q)*(sq[fr+1]-sq[fl]); } } return ans; } int main() { Mod32::set_mod(mod); scanf("%d",&n); fac[0]=1u; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*(u32)i; for (int i=0;i<=n;i++) fnv[i]=(u32)powmod(fac[i].get(),mod-2); rep(i,0,3) { scanf("%d%s",r+i,s[i]); } Mod32 ans=calc(r[0])+calc(r[1])+calc(r[2]); ans=ans-calc(r[0],r[1],s[0],s[1])-calc(r[0],r[2],s[0],s[2])-calc(r[1],r[2],s[1],s[2]); ans+=calc(r[0],r[1],r[2],s[0],s[1],s[2]); printf("%d\n",(int)ans.get()); } |