/* one zero 000 111 000 001 110 001 010 101 010 011 100 011 a+b+c+d<=ra a+b+C-c+D-d<=rb a+B-b+c+D-d<=rc */ #include<cstdio> const int N=10005,P=1000000007; typedef unsigned int uint32; typedef long long int64; typedef unsigned long long uint64; typedef uint32 word; typedef uint64 dword; typedef int sword; const int word_bits=sizeof(word)*8; word mod,Modinv,r2; struct UnsafeMod{ word x; UnsafeMod(): x(0) {} UnsafeMod(word _x): x(init(_x)) {} UnsafeMod& operator += (const UnsafeMod& rhs) { (x += rhs.x) >= mod && (x -= mod); return *this; } UnsafeMod& operator -= (const UnsafeMod& rhs) { sword(x -= rhs.x) < 0 && (x += mod); return *this; } UnsafeMod& operator *= (const UnsafeMod& rhs) { x = reduce(dword(x) * rhs.x); return *this; } UnsafeMod operator + (const UnsafeMod &rhs) const { return UnsafeMod(*this) += rhs; } UnsafeMod operator - (const UnsafeMod &rhs) const { return UnsafeMod(*this) -= rhs; } UnsafeMod operator * (const UnsafeMod &rhs) const { return UnsafeMod(*this) *= rhs; } UnsafeMod pow(uint64 e) const { UnsafeMod ret(1); for (UnsafeMod base = *this; e; e >>= 1, base *= base) { if (e & 1) ret *= base; } return ret; } word get() const { return reduce(x); } static word modulus() { return mod; } static word init(word w) { return reduce(dword(w) * r2); } static void set_mod(word m) { mod = m; Modinv = mul_inv(mod); r2 = -dword(mod) % mod; } static word reduce(dword x) { word y = word(x >> word_bits) - word((dword(word(x) * Modinv) * mod) >> word_bits); return sword(y) < 0 ? y + mod : y; } static word mul_inv(word n, int e = 6, word x = 1) { return !e ? x : mul_inv(n, e - 1, x * (2 - x * n)); } }ans,f[N],g[N],s[N][N]; int n,i,lim[3],fac[N],inv[N];char a[3][N]; inline UnsafeMod getC(int n,int m){ if(n<m)return 0; UnsafeMod ret=fac[n]; ret*=inv[m]; return ret*inv[n-m]; } void pre(int n,UnsafeMod*f){for(int i=0;i<N;i++)f[i]=getC(n,i);} UnsafeMod one(int x){ UnsafeMod ret=0; for(int i=0;i<=lim[x];i++)ret+=getC(n,i); return ret; } UnsafeMod two(int x,int y){ UnsafeMod ret=0; int cnt=0,i,j; for(i=0;i<n;i++)if(a[x][i]==a[y][i])cnt++; pre(cnt,f); pre(n-cnt,g); for(i=0;i<=cnt;i++)for(j=0;j<=n-cnt;j++){ if(i+j>lim[x])break; if(i+n-cnt-j>lim[y])continue; ret+=f[i]*g[j]; } return ret; } UnsafeMod three(){ UnsafeMod ret=0; int i,j,A=0,B=0,C=0,D=0,ra=lim[0],rb=lim[1],rc=lim[2]; for(i=0;i<n;i++){ int x=a[0][i]-'0',y=a[1][i]-'0',z=a[2][i]-'0'; y^=x,z^=x; if(y==0&&z==0)A++; if(y==0&&z==1)B++; if(y==1&&z==0)C++; if(y==1&&z==1)D++; } /* a+b+c+d<=ra a+b+C-c+D-d<=rb a+B-b+c+D-d<=rc */ pre(C,f),pre(D,g); for(i=0;i<=C;i++)for(j=0;j<=D;j++)s[i+j][i-j+D]+=f[i]*g[j]; //-D<=i-j<=C //0<=i-j+D<=C+D int m=C+D; for(i=0;i<=m;i++)for(j=0;j<=m;j++){ if(i)s[i][j]+=s[i-1][j]; if(j)s[i][j]+=s[i][j-1]; if(i&&j)s[i][j]-=s[i-1][j-1]; } pre(A,f),pre(B,g); for(i=0;i<=A;i++)for(j=0;j<=B&&i+j<=ra;j++){ int l=i+j+C+D-rb; int r=ra-i-j; if(l<0)l=0; if(r>m)r=m; if(l>r)continue; int k=rc-i+j-B; if(k<0)continue; if(k>m)k=m; UnsafeMod tmp=s[r][k]; if(l)tmp-=s[l-1][k]; ret+=tmp*f[i]*g[j]; } return ret; } int main(){ UnsafeMod::set_mod(P); scanf("%d",&n); for(i=0;i<3;i++)scanf("%d%s",&lim[i],a[i]); for(fac[0]=i=1;i<=n;i++)fac[i]=1LL*fac[i-1]*i%P; for(inv[0]=inv[1]=1,i=2;i<=n;i++)inv[i]=1LL*(P-inv[P%i])*(P/i)%P; for(i=2;i<=n;i++)inv[i]=1LL*inv[i-1]*inv[i]%P; ans=one(0)+one(1)+one(2)-two(0,1)-two(0,2)-two(1,2)+three(); printf("%u",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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | /* one zero 000 111 000 001 110 001 010 101 010 011 100 011 a+b+c+d<=ra a+b+C-c+D-d<=rb a+B-b+c+D-d<=rc */ #include<cstdio> const int N=10005,P=1000000007; typedef unsigned int uint32; typedef long long int64; typedef unsigned long long uint64; typedef uint32 word; typedef uint64 dword; typedef int sword; const int word_bits=sizeof(word)*8; word mod,Modinv,r2; struct UnsafeMod{ word x; UnsafeMod(): x(0) {} UnsafeMod(word _x): x(init(_x)) {} UnsafeMod& operator += (const UnsafeMod& rhs) { (x += rhs.x) >= mod && (x -= mod); return *this; } UnsafeMod& operator -= (const UnsafeMod& rhs) { sword(x -= rhs.x) < 0 && (x += mod); return *this; } UnsafeMod& operator *= (const UnsafeMod& rhs) { x = reduce(dword(x) * rhs.x); return *this; } UnsafeMod operator + (const UnsafeMod &rhs) const { return UnsafeMod(*this) += rhs; } UnsafeMod operator - (const UnsafeMod &rhs) const { return UnsafeMod(*this) -= rhs; } UnsafeMod operator * (const UnsafeMod &rhs) const { return UnsafeMod(*this) *= rhs; } UnsafeMod pow(uint64 e) const { UnsafeMod ret(1); for (UnsafeMod base = *this; e; e >>= 1, base *= base) { if (e & 1) ret *= base; } return ret; } word get() const { return reduce(x); } static word modulus() { return mod; } static word init(word w) { return reduce(dword(w) * r2); } static void set_mod(word m) { mod = m; Modinv = mul_inv(mod); r2 = -dword(mod) % mod; } static word reduce(dword x) { word y = word(x >> word_bits) - word((dword(word(x) * Modinv) * mod) >> word_bits); return sword(y) < 0 ? y + mod : y; } static word mul_inv(word n, int e = 6, word x = 1) { return !e ? x : mul_inv(n, e - 1, x * (2 - x * n)); } }ans,f[N],g[N],s[N][N]; int n,i,lim[3],fac[N],inv[N];char a[3][N]; inline UnsafeMod getC(int n,int m){ if(n<m)return 0; UnsafeMod ret=fac[n]; ret*=inv[m]; return ret*inv[n-m]; } void pre(int n,UnsafeMod*f){for(int i=0;i<N;i++)f[i]=getC(n,i);} UnsafeMod one(int x){ UnsafeMod ret=0; for(int i=0;i<=lim[x];i++)ret+=getC(n,i); return ret; } UnsafeMod two(int x,int y){ UnsafeMod ret=0; int cnt=0,i,j; for(i=0;i<n;i++)if(a[x][i]==a[y][i])cnt++; pre(cnt,f); pre(n-cnt,g); for(i=0;i<=cnt;i++)for(j=0;j<=n-cnt;j++){ if(i+j>lim[x])break; if(i+n-cnt-j>lim[y])continue; ret+=f[i]*g[j]; } return ret; } UnsafeMod three(){ UnsafeMod ret=0; int i,j,A=0,B=0,C=0,D=0,ra=lim[0],rb=lim[1],rc=lim[2]; for(i=0;i<n;i++){ int x=a[0][i]-'0',y=a[1][i]-'0',z=a[2][i]-'0'; y^=x,z^=x; if(y==0&&z==0)A++; if(y==0&&z==1)B++; if(y==1&&z==0)C++; if(y==1&&z==1)D++; } /* a+b+c+d<=ra a+b+C-c+D-d<=rb a+B-b+c+D-d<=rc */ pre(C,f),pre(D,g); for(i=0;i<=C;i++)for(j=0;j<=D;j++)s[i+j][i-j+D]+=f[i]*g[j]; //-D<=i-j<=C //0<=i-j+D<=C+D int m=C+D; for(i=0;i<=m;i++)for(j=0;j<=m;j++){ if(i)s[i][j]+=s[i-1][j]; if(j)s[i][j]+=s[i][j-1]; if(i&&j)s[i][j]-=s[i-1][j-1]; } pre(A,f),pre(B,g); for(i=0;i<=A;i++)for(j=0;j<=B&&i+j<=ra;j++){ int l=i+j+C+D-rb; int r=ra-i-j; if(l<0)l=0; if(r>m)r=m; if(l>r)continue; int k=rc-i+j-B; if(k<0)continue; if(k>m)k=m; UnsafeMod tmp=s[r][k]; if(l)tmp-=s[l-1][k]; ret+=tmp*f[i]*g[j]; } return ret; } int main(){ UnsafeMod::set_mod(P); scanf("%d",&n); for(i=0;i<3;i++)scanf("%d%s",&lim[i],a[i]); for(fac[0]=i=1;i<=n;i++)fac[i]=1LL*fac[i-1]*i%P; for(inv[0]=inv[1]=1,i=2;i<=n;i++)inv[i]=1LL*(P-inv[P%i])*(P/i)%P; for(i=2;i<=n;i++)inv[i]=1LL*inv[i-1]*inv[i]%P; ans=one(0)+one(1)+one(2)-two(0,1)-two(0,2)-two(1,2)+three(); printf("%u",ans.get()); } |