#include <bits/stdc++.h> using namespace std; /* 题意有点模糊不全,敌方选人如何选不知道 我们假设敌方选人和我方选人一样,选的顺序不一样,即使选的英雄一样也不行 禁英雄,只要禁的一样,那么就说是同一种情况 那么此题就转成排列组合 我方先选出人来,然后乘A(95,5)*C(90,5)*C(85,5) 如何计算我放选人的组合数 状压dp dp[i][j]表示选到第i个英雄,我方五人是否选人的情况为j时排列组合数 j转换成二进制来表示五人的选人情况,1代表选人了,0代表没选 两种情况 选这个英雄 if(j&1<<k&&s[k][i]) dp[i][j]=max(dp[i][j],dp[i-1][j^(1<<k)]+dp[i][j])%mod; 不选 dp[i][j]=max(dp[i][j],dp[i][j]+dp[i-1][j])%mod; */ typedef long long ll; const int maxn=109; ll dp[maxn][(1<<5)+10]; int s[6][maxn]; ll mod=1000000007; ll A(ll n,ll m) { ll sum=1; for(ll i=n; i>n-m; i--) sum=sum*i; return sum; } ll C(ll n,ll m) { ll sum=1; for(ll i=1; i<=m; i++) sum=sum*(n-i+1)/i; return sum; } int main() { //多组样例输入呀 while(~scanf("%1d",&s[1][1])) { for(int j=2;j<=100;j++)scanf("%1d",&s[1][j]); for(int i=2; i<=5; i++) for(int j=1; j<=100; j++) scanf("%1d",&s[i][j]); memset(dp,0,sizeof(dp)); for(int i=0;i<5;i++) if(s[i+1][1])dp[1][1<<i]=1; dp[1][0]=1; //dp[0][0]=1;//两种方式都可以 for(int i=2; i<=100; i++) for(int j=0; j<(1<<5); j++) { for(int k=0; k<5; k++) { if((j&(1<<k))&&s[k+1][i]) dp[i][j]=(dp[i-1][j^(1<<k)]+dp[i][j])%mod; } dp[i][j]=(dp[i][j]+dp[i-1][j])%mod; } ll ans=dp[100][(1<<5)-1]; ans=(ans*A(95,5))%mod*((C(90,5)%mod*C(85,5))%mod); printf("%lld ",ans%mod); } return 0; }