D - LOL UVALive - 8521 (状压dp)
https://nanti.jisuanke.com/t/A1616
思路:dp[i][j]表示前i列里面选了情况j有多少种组合方案
#include<bits/stdc++.h> using namespace std; const int N = 2e5+5; typedef long long ll; const ll mod = 1000000007; string s[5]; ll f[101],C[101][101]; ll dp[107][1<<5]; ll q_pow(ll a,ll n){ ll ans=1; ll base=a; while(n){ if(n&1) ans=(ans*base)%mod; base=base*base%mod; n>>=1; } return ans; } ll inv(ll a,ll b){ return q_pow(a,b-2); } ll A(ll n,ll m){ if(n<m) return 0; return f[n]*inv(f[n-m],mod)%mod; } int main(){ f[0]=1; for(ll i=1;i<=100;i++) f[i]=f[i-1]*i%mod; C[0][0]=1; for(int i=1;i<=100;i++){ C[i][0]=1; for(int j=1;j<=i;j++){ C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod; } } ios::sync_with_stdio(false); while(cin>>s[0]){ for(int i=1;i<5;i++) cin>>s[i]; memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int i=1;i<=100;i++){ for(int j=0;j<(1<<5);j++){ for(int k=0;k<5;k++){ if((j&(1<<k))&&(s[k][i-1]=='1')){ dp[i][j]=(dp[i][j]+dp[i-1][j^(1<<k)])%mod; } } dp[i][j]+=dp[i-1][j]%mod; } } ll ans=dp[100][(1<<5)-1]; cout<<ans*A(95,5)%mod*C[90][5]%mod*C[85][5]%mod<<endl; } }