ACM-ICPC 2017 Asia Xi'an J LOL 【暴力 && 排列组合】

任意门:https://nanti.jisuanke.com/t/20750

J - LOL

5 friends play LOL together . Every one should BAN one character and PICK one character . The enemy should BAN 55 characters and PICK 55 characters . All these 2020 heroes must be different .

Every one can BAN any heroes by his personal washes . But he can only PICK heroes which he has bought .

Suppose the enemy can PICK or BAN any heroes. How many different ways are there satisfying the conditions?

For example , a valid way is :

Player 11 : picks hero 11, bans hero 22

Player 22 : picks hero 33, bans hero 44

Player 33 : picks hero 5, bans hero 66

Player 44 : picks hero 77, bans hero 88

Player 55 : picks hero 99, bans hero 1010

Enemies pick heroes 11,12,13,14,1511,12,13,14,15 , ban heroes 16,17,18,19,2016,17,18,19,20 .

Input

The input contains multiple test cases.(No more than 2020)

In each test case . there’s 55 strings S[1] sim S[5]S[1]S[5] ,respectively whose lengths are 100100 , For the ii-th person if he has bought the jj-th hero, the jj-th character of S[i]S[i] is '11', or '00' if not. The total number of heroes is exactly 100100 .

Output

For each test case , print the answer mod 10000000071000000007 in a single line .

样例输入

0110011100011001001100011110001110001110001010010111111110101010010011010000110100011001001111101011
1000111101111110110100001101001101010001111001001011110001111110101000011101000001011100001001011010
0100101100011110011100110110011100111100010010011001111110101111111000000110001110000110001100001110
1110010101010001000110100011101010001010000110001111111110101010000000001111001110110101110000010011
1000010011111110001101100000101001110100011000111010011111110110111010011111010110101111011111011011

样例输出

515649254

题意概括:

五个二进制数代表我方 5 人所拥有的英雄,0为没有,1为有。

敌方5人什么英雄都有,问有多少种 Ban Pick方案。

每人都可以选一个自己拥有的英雄和 ban 掉任何一个英雄,最后选的和禁止掉的20个英雄都不相同。

解题思路:

暴力枚举我方选英雄的方案

敌方选英雄的方案为 A(95, 5)

我方禁英雄的方案为 C(90, 5)

敌方禁英雄的方案为 C(85,5)

关于暴力的优化和剪枝:

如果是传统暴力枚举每个人选不同英雄的方案,需要五层 for(0, 100) 循环,TL!

优化只枚举前四个人的方案, 第五个能选的英雄只能是前面没有选的,缩小了一层循环。

关于剪枝 前面选过的不要选咯

AC code:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 #define INF 0x3f3f3f3f
 6 #define LL long long
 7 using namespace std;
 8 const int mod = 1e9+7;
 9 const int MAXN = 105;
10 
11 char a[MAXN], b[MAXN], c[MAXN], d[MAXN], e[MAXN];
12 LL A(LL N, LL R)
13 {
14     LL sum = 1;
15     for(int i = 0; i < R; i++)
16         sum *= N-i;
17     return sum;
18 }
19 
20 LL C(LL N, LL R)
21 {
22     LL sum = 1;
23     for(int i = 1; i <= R; i++)
24         sum = sum* (N+1-i)/i;
25     return sum;
26 }
27 
28 int main()
29 {
30     while(~scanf("%s%s%s%s%s", a, b, c, d, e)){
31         int len = 0;
32         for(int i = 0; i < 100; i++){
33             if(e[i] == '1') len++;
34         }
35         LL ans = 0;
36         for(int i = 0; i < 100; i++){
37             if(a[i] == '0') continue;
38             for(int j = 0; j < 100; j++){
39                 if(b[j] == '0' || j == i) continue;
40                 for(int k = 0; k < 100; k++){
41                     if(c[k] == '0' || k == i || k == j) continue;
42                     for(int p = 0; p < 100; p++){
43                         if(d[p] == '0' || p == i || p == j || p == k) continue;
44                         int res = len;
45                         if(e[i] == '1') res--;
46                         if(e[j] == '1') res--;
47                         if(e[k] == '1') res--;
48                         if(e[p] == '1') res--;
49                         if(res>=0)      ans+=res;
50                     }
51                 }
52             }
53         }
54         ans = ans*A(95, 5)%mod*C(90, 5)%mod*C(85, 5)%mod;
55         printf("%lld
", ans);
56     }
57     return 0;
58 }
View Code
原文地址:https://www.cnblogs.com/ymzjj/p/9865969.html