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
| #include<stack> #include<vector> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;
#define upd(a,b) ((a)=(a)|(b)) #define cs const int & const int N=5e3+10,M=2e6+10,MOD=1e9+7;
inline int Add(cs a,cs b){return a+b>=MOD? a+b-MOD:a+b;} inline int Mul(cs a,cs b){return 1ll*a*b%MOD;} inline int Pow(int a,int b){int r=1;while(b){if(b&1)r=Mul(r,a);a=Mul(a,a),b>>=1;}return r;}
bool debug; int n,A,B,ndfn,nscc; char str[M]; bool instk[N]; vector<bool> bag[N],fbag[N]; stack<int> stk; int fac[N],ifac[N],siz[N],fsiz[N],dfn[N],low[N],scc[N],mn[N],mx[N],tbag[M],fcnt[N];
struct GRPAH{ int head[N],to[N*N],nxt[N*N],ncnt; void AddEdge(cs u,cs v){ ncnt++; nxt[ncnt]=head[u],to[ncnt]=v; head[u]=ncnt; } inline int operator [](cs u){return head[u];} }Gr;
inline int Comb(cs a,cs b){return (a<0 || b<0 || a>b)? 0:Mul(fac[b],Mul(ifac[a],ifac[b-a]));} void Init(){ fac[0]=1;for(int i=1;i<N;i++) fac[i]=Mul(fac[i-1],i); ifac[N-1]=Pow(fac[N-1],MOD-2);for(int i=N-2;i>=0;i--) ifac[i]=Mul(ifac[i+1],i+1); } void Input(){ scanf("%d%d%d",&n,&A,&B); for(int i=1;i<=n;i++){ scanf("%s",str+1); for(int j=1;j<=n;j++) if(str[j]=='1') Gr.AddEdge(i,j); } for(int i=1;i<=n;i++){ scanf("%d%s",&siz[i],str); if(siz[1]==831484) debug=true; for(int j=0;j<siz[i];j++){ bag[i].push_back(str[j]-'0'); mn[i]+=str[j]-'0'; } } } inline int GCD(cs a,cs b){return b? GCD(b,a%b):a;} void Tarjan(cs u){ dfn[u]=low[u]=++ndfn; instk[u]=true,stk.push(u); for(int it=Gr[u];it;it=Gr.nxt[it]){ int v=Gr.to[it]; if(!dfn[v]) Tarjan(v),low[u]=min(low[u],low[v]); else if(instk[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]){ int tmp=0;nscc++; do{ tmp=stk.top(),stk.pop(); instk[tmp]=false; scc[tmp]=nscc; fsiz[nscc]=GCD(fsiz[nscc],siz[tmp]); }while(tmp!=u); fbag[nscc].resize(fsiz[nscc]); } } void PartGraph(){ for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i); for(int i=1;i<=n;i++) for(int j=0;j<siz[i];j++) upd(fbag[scc[i]][j%fsiz[scc[i]]],bag[i][j]); for(int i=nscc;i>1;i--){ int tsiz=GCD(fsiz[i],fsiz[i-1]); int u=i,v=i-1; for(int j=0;j<tsiz;j++) tbag[j]=0; for(int j=0;j<fsiz[u];j++) upd(tbag[j%tsiz],fbag[u][j]); for(int j=0;j<fsiz[v];j++) upd(fbag[v][j],tbag[j%tsiz]); } for(int i=1;i<=nscc;i++) for(int j=0;j<fsiz[i];j++) fcnt[i]+=fbag[i][j]; for(int i=1;i<=n;i++) mx[i]=siz[i]/fsiz[scc[i]]*fcnt[scc[i]]; } int PartMath(){ int ans=0; for(int i=1;i<=n;i++){ int mus=0,may=0; for(int j=1;j<=n;j++){ if(mx[i]<mn[j]) mus++; else if(mx[i]<mx[j] || (mx[i]==mx[j] && i<j)) may++; } if(mus>=A) continue; for(int j=min(B,min(A-1-mus,may));j+mus+1>=B;j--) ans=Add(ans,Mul(Comb(j,may),Comb(B-1-j,mus))); } return ans; } int main(){ Init(); Input(); PartGraph(); printf("%d\n",PartMath()); return 0; }
|