UVALive 8521 LOL 状压dp

题目链接: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
*/

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值