#include <iostream> #include <string> #include <vector> #include <algorithm> using namespace std; const int MOD=1000000007; //NUMERIC SECTOR long long power(long long b, int e){ if(e==0) return 1; long long x = power(b, e/2); x = (x*x)%MOD; return (e%2)?(x*b%MOD):x; } long long inverse(long long x){ return power(x, MOD-2); } vector<long long>FactTab,InvFactTab; void prepareFactorialTab(int mx){ if(FactTab.empty()){ FactTab.push_back(1); FactTab.push_back(1); InvFactTab.push_back(1); InvFactTab.push_back(1); } while((int)FactTab.size()<=mx){ FactTab.push_back(FactTab.back()*FactTab.size()%MOD); InvFactTab.push_back(inverse(FactTab.back())); } } long long binom(int n, int k){ //return FactTab[n]*inverse(FactTab[k])%MOD*inverse(FactTab[n-k])%MOD; return FactTab[n]*InvFactTab[k]%MOD*InvFactTab[n-k]%MOD; } //N-DIMENSIONAL SECTOR struct Kula{ int r; string O; }; long long Mono(const Kula &K){ long long wnk=0; for(int diff=0;diff<=K.r;diff++) wnk = (wnk + binom(K.O.length(), diff))%MOD; //cerr << "Mono returns " << wnk << endl; return wnk; } long long Di(const Kula &K1, const Kula &K2){ int alpha=0, beta=0; for(int i=0;i<(int)K1.O.length();i++) if(K1.O[i]==K2.O[i]) alpha++; else beta++; long long wnk=0; for(int diff=0;diff<=K1.r;diff++) for(int gamma=0;gamma<=min(alpha,diff);gamma++) if(diff-gamma<=beta && 2*gamma+beta-diff<=K2.r) wnk = (wnk+binom(alpha, gamma)*binom(beta, diff-gamma))%MOD; //cerr << "Di returns " << wnk << endl; return wnk; } long long Tri(const Kula &K1, const Kula &K2, const Kula &K3){ int alpha=0, beta=0, gamma=0, fi=0; for(int i=0;i<(int)K1.O.length();i++) if(K1.O[i]==K2.O[i]){ if(K2.O[i]==K3.O[i]) alpha++; else beta++; } else{ if(K2.O[i]==K3.O[i]) gamma++; else fi++; } long long wnk=0; for(int diff=0;diff<=K1.r;diff++) for(int lambda=0;lambda<=min(diff, alpha);lambda++) for(int omega=0;omega<=min(diff-lambda, beta);omega++) for(int psi=0;psi<=min(diff-lambda-omega,gamma);psi++){ int epsilon=diff-lambda-omega-psi; if(epsilon<=fi && lambda+omega+gamma-psi+fi-epsilon<=K2.r && lambda+beta-omega+gamma-psi+epsilon<=K3.r) wnk = (wnk+binom(alpha,lambda)*binom(beta,omega)%MOD*binom(gamma,psi)%MOD*binom(fi,diff-lambda-omega-psi))%MOD; } //cerr << "Tri returns " << wnk << endl; return wnk; } //THE BORING REST int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; prepareFactorialTab(n); Kula A,B,C; cin >> A.r >> A.O >> B.r >> B.O >> C.r >> C.O; long long wnk = Mono(A) + Mono(B) + Mono(C) - Di(A,B) - Di(B,C) - Di(C,A) + Tri(A,B,C); wnk = (wnk + 42ll*MOD)%MOD; cout << wnk << "\n"; return 0; }
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 | #include <iostream> #include <string> #include <vector> #include <algorithm> using namespace std; const int MOD=1000000007; //NUMERIC SECTOR long long power(long long b, int e){ if(e==0) return 1; long long x = power(b, e/2); x = (x*x)%MOD; return (e%2)?(x*b%MOD):x; } long long inverse(long long x){ return power(x, MOD-2); } vector<long long>FactTab,InvFactTab; void prepareFactorialTab(int mx){ if(FactTab.empty()){ FactTab.push_back(1); FactTab.push_back(1); InvFactTab.push_back(1); InvFactTab.push_back(1); } while((int)FactTab.size()<=mx){ FactTab.push_back(FactTab.back()*FactTab.size()%MOD); InvFactTab.push_back(inverse(FactTab.back())); } } long long binom(int n, int k){ //return FactTab[n]*inverse(FactTab[k])%MOD*inverse(FactTab[n-k])%MOD; return FactTab[n]*InvFactTab[k]%MOD*InvFactTab[n-k]%MOD; } //N-DIMENSIONAL SECTOR struct Kula{ int r; string O; }; long long Mono(const Kula &K){ long long wnk=0; for(int diff=0;diff<=K.r;diff++) wnk = (wnk + binom(K.O.length(), diff))%MOD; //cerr << "Mono returns " << wnk << endl; return wnk; } long long Di(const Kula &K1, const Kula &K2){ int alpha=0, beta=0; for(int i=0;i<(int)K1.O.length();i++) if(K1.O[i]==K2.O[i]) alpha++; else beta++; long long wnk=0; for(int diff=0;diff<=K1.r;diff++) for(int gamma=0;gamma<=min(alpha,diff);gamma++) if(diff-gamma<=beta && 2*gamma+beta-diff<=K2.r) wnk = (wnk+binom(alpha, gamma)*binom(beta, diff-gamma))%MOD; //cerr << "Di returns " << wnk << endl; return wnk; } long long Tri(const Kula &K1, const Kula &K2, const Kula &K3){ int alpha=0, beta=0, gamma=0, fi=0; for(int i=0;i<(int)K1.O.length();i++) if(K1.O[i]==K2.O[i]){ if(K2.O[i]==K3.O[i]) alpha++; else beta++; } else{ if(K2.O[i]==K3.O[i]) gamma++; else fi++; } long long wnk=0; for(int diff=0;diff<=K1.r;diff++) for(int lambda=0;lambda<=min(diff, alpha);lambda++) for(int omega=0;omega<=min(diff-lambda, beta);omega++) for(int psi=0;psi<=min(diff-lambda-omega,gamma);psi++){ int epsilon=diff-lambda-omega-psi; if(epsilon<=fi && lambda+omega+gamma-psi+fi-epsilon<=K2.r && lambda+beta-omega+gamma-psi+epsilon<=K3.r) wnk = (wnk+binom(alpha,lambda)*binom(beta,omega)%MOD*binom(gamma,psi)%MOD*binom(fi,diff-lambda-omega-psi))%MOD; } //cerr << "Tri returns " << wnk << endl; return wnk; } //THE BORING REST int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; prepareFactorialTab(n); Kula A,B,C; cin >> A.r >> A.O >> B.r >> B.O >> C.r >> C.O; long long wnk = Mono(A) + Mono(B) + Mono(C) - Di(A,B) - Di(B,C) - Di(C,A) + Tri(A,B,C); wnk = (wnk + 42ll*MOD)%MOD; cout << wnk << "\n"; return 0; } |