题目链接:https://vj.ti12z.cn/7d1b9ea0526196168eeaf7fd5016f713?v=1562731630
题意:
你和你的朋友共5个人在玩游戏,有100个英雄,每次开局前要进行角色选择,你们5个人要分别选择不同的要用的英雄以及禁用的英雄,敌方机器只要一起分配5个要选以及禁用的即可,但是你们5个人选择的角色只能是已有的,禁用和敌方的任意角色都可以从100个里面选,问你有多少种分配方式。
做法:
其实只要算出自己能选的角色种类情况即可,状压dp,dp[i][j]代表选到第i个英雄的时候,己方队伍中已选为1,未选为0, 状态为j的情况的方案数。
不是很难,看看代码应该也能知道了。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i =(int) a;i <=(int)b;i++)
using namespace std;
typedef long long ll;
const int maxn=200005;
const int maxm=(1<<5);
const int mod=(int)1e9+7;
int dp[105][maxm+5];
char s[10][105];
ll fi=1,se=1,th=1;
ll quick(ll a,ll b){
ll ret=1;
while(b){
if(b&1) ret=ret*a%mod;
a=a*a%mod;
b/=2;
}
return ret;
}
int main() {
ll ffi=95,fse=90,fth=85;
for(int i=1;i<=5;i++){
fi=fi*ffi%mod;
se=(fse*se*quick(i,mod-2))%mod;
th=(th*fth*quick(i,mod-2))%mod;
ffi--,fse--,fth--;
}
while(~scanf("%s",s[0]+1)){
for(int i=1;i<5;i++) scanf("%s",s[i]+1);
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=100;i++){
for(int j=0;j<maxm;j++){
for(int k=0;k<5;k++){
if(j&(1<<k)&&s[k][i]=='1'){
dp[i][j]=(dp[i][j]+dp[i-1][j-(1<<k)])%mod;
}
}
dp[i][j]=(dp[i][j]+dp[i-1][j])%mod;
}
}
printf("%lld\n",dp[100][maxm-1]*fi%mod*se%mod*th%mod);
}
return 0;
}
/*
0110011100011001001100011110001110001110001010010111111110101010010011010000110100011001001111101011
1000111101111110110100001101001101010001111001001011110001111110101000011101000001011100001001011010
0100101100011110011100110110011100111100010010011001111110101111111000000110001110000110001100001110
1110010101010001000110100011101010001010000110001111111110101010000000001111001110110101110000010011
1000010011111110001101100000101001110100011000111010011111110110111010011111010110101111011111011011
*/