UVALive ~ 8521 ~ LOL (暴力 + 组合数学)2017ICPC Xi'an

题意:有十个人在玩LOL,总共有100个英雄,每个人可以选一个和BAN一个,问你们十个人有多少种不同的BAN选方案,取余1e9+7?输入5个01串表示我方五个人分别拥有的英雄,假设对面英雄全有。

①任意两个人不能选或BAN同一个英雄

②只能选自己有的英雄。

③12345召唤师选英雄12345和54321是不同的方案,12345召唤师BAN英雄12345和54321是相同的方案。


思路:统计第五个人有的英雄数,暴力枚举我方前四个人的选人,第五个人有的英雄数 - 被前四个人选到且自己拥有的英雄个数,累计这个结果就是我方选人的方案数记为ans。

对面五个人的选英雄方案数为A(95,5)。

我方BAN五个英雄的方案数为C(90,5),敌方BAN五个英雄的方案数为C(85,5)。

按照乘法计数原理可得ans * A(95, 5) * C(90, 5) * C(85, 5)就是答案。记得取模,乘一步取模一次。


#include<bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
typedef long long ll;
const int MOD = 1000000007;
char s[6][105];
int a[6];
ll A(ll n, ll r)//排列数
{
    ll sum = 1;
    for (int i = 0; i < r; i++)
        sum *= n-i;
    return sum;
}
ll C(ll n, ll r)//组合数
{
    ll sum = 1;
    for (int i = 1; i <= r; i++)
        sum = sum * (n+1-i)/i;
    return sum;
}
int main()
{
    while (~scanf("%s", s[0]))
    {
        for (int i = 1; i < 5; i++) scanf("%s", s[i]);
        for (int i = 0; i < 5; i++) a[i] = count(s[i], s[i]+100, '1');

        //for (int i = 0; i < 5; i++) printf("%d ", a[i]); printf("\n");

        ll ans = 0;
        for (int i0 = 0; i0 < 100; i0++)
        {
            if (s[0][i0] == '0') continue;
            for (int i1 = 0; i1 < 100; i1++)
            {
                if (s[1][i1] == '0') continue;
                if (i0 == i1) continue;
                for (int i2 = 0; i2 < 100; i2++)
                {
                    if (s[2][i2] == '0') continue;
                    if (i0 == i2 || i1 == i2) continue;
                    for (int i3 = 0; i3 < 100; i3++)
                    {
                        if (s[3][i3] == '0') continue;
                        if (i0 == i3 || i1 == i3 || i2 == i3) continue;
                        int cnt = 0;
                        if (s[4][i0] == '1') cnt++;
                        if (s[4][i1] == '1') cnt++;
                        if (s[4][i2] == '1') cnt++;
                        if (s[4][i3] == '1') cnt++;
                        ans = (ans + a[4] - cnt)%MOD;
                    }
                }
            }
        }
        ll tmp = A(95, 5) * C(90, 5) % MOD * C(85, 5) % MOD;
        printf("%lld\n", ans*tmp%MOD);
    }
    return 0;
}
/*
0110011100011001001100011110001110001110001010010111111110101010010011010000110100011001001111101011
1000111101111110110100001101001101010001111001001011110001111110101000011101000001011100001001011010
0100101100011110011100110110011100111100010010011001111110101111111000000110001110000110001100001110
1110010101010001000110100011101010001010000110001111111110101010000000001111001110110101110000010011
1000010011111110001101100000101001110100011000111010011111110110111010011111010110101111011111011011
*/
//515649254

猜你喜欢

转载自blog.csdn.net/zscdst/article/details/80525588