UVA11806 Cheerleaders
Cheerleaders
大意:n * m个网格中放若干石子,要求最上面一行、最下面一行、最左边一列、最右边一列必须有石子
没有石子比有石子好求,考虑容斥
小集合是最上面一行没有、最下面一行没有、最左边一列没有、最右边一列没有
注意MOD不是质数!
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #define min(a, b) ((a) < (b) ? (a) : (b)) 9 #define max(a, b) ((a) > (b) ? (a) : (b)) 10 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 11 inline void swap(long long &a, long long &b) 12 { 13 long long tmp = a;a = b;b = tmp; 14 } 15 inline void read(long long &x) 16 { 17 x = 0;char ch = getchar(), c = ch; 18 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 19 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 20 if(c == '-') x = -x; 21 } 22 23 const long long INF = 0x3f3f3f3f; 24 const long long MAXK = 500; 25 const long long MAXN = 20; 26 const long long MOD = 1000007; 27 28 long long n,m,k,t,C[MAXN * MAXN + 5][MAXK + 5]; 29 30 int main() 31 { 32 read(t);long long cnt = 0; 33 C[0][0] = 1; 34 for(register int i = 0;i <= MAXN * MAXN;++ i) 35 { 36 C[i][0] = 1;C[i][i] = 1; 37 for(register int j = 1;j <= i;++ j) 38 C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD; 39 } 40 for(;t;--t) 41 { 42 ++ cnt; 43 read(n), read(m), read(k); 44 long long ans = 0; 45 for(long long S = 0;S < 16;++ S) 46 { 47 long long num = 0, a = n, b = m; 48 if(S & 1) -- a, ++ num; 49 if(S & 2) -- b, ++ num; 50 if(S & 4) -- a, ++ num; 51 if(S & 8) -- b, ++ num; 52 if(num & 1) ans = (ans - C[a* b][k] + MOD) % MOD; 53 else ans = (ans + C[a * b][k]) % MOD; 54 } 55 printf("Case %lld: %lld\n", cnt, ans); 56 } 57 return 0; 58 }