2014西安现场赛F题 UVALA 7040
题意:求在m种颜色中挑选k种颜色,给n个花朵涂色有几种方法。
分析:画图可以发现,基本的公式就是k ×(k-1)^(n-1)。但这仅保证了相邻颜色不同,总颜色数不超过k种,并没有保证恰好出现k种颜色;接着就是一个容斥问题,上述计算方法中包含了只含有2、3、…、(k-1)种颜色的情况,需要通过容斥原理去除。假设出现p (2 <= p <= k-1)种颜色,从k种颜色中选取p种进行涂色,方案数为C(k,p) × p × (p-1)^(n-1) ;总的方案数就是C(m,k) × ( k × (k-1)^(n-1) + ∑((-1)^p × C(k, p) × p × (p-1)^(n-1) )。
图示法:
一共8种情况,但是有两种是只有两种颜色的,需要减掉。
TLE 原因:1)逆元没有打表;2)参数传多余了,本来MOD是全局变量,但是模板上有这一项,就当参数传上了,结果就TLE了。
这是我们去年在西安现场比赛的时候做的题目,就卡在这道题目里,一直TLE了,始终没能改过来,今天题目重现了一次,仍旧TLE。。。。。。可见学新知识的时候一点也不扎实。
1 #include <cstdio> 2 #include <iostream> 3 #include <sstream> 4 #include <cmath> 5 #include <cstring> 6 #include <cstdlib> 7 #include <string> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <queue> 12 #include <stack> 13 #include <algorithm> 14 using namespace std; 15 #define ll long long 16 #define _cle(m, a) memset(m, a, sizeof(m)) 17 #define repu(i, a, b) for(int i = a; i < b; i++) 18 #define repd(i, a, b) for(int i = b; i >= a; i--) 19 #define sfi(n) scanf("%d", &n) 20 #define pfi(n) printf("%d\n", n) 21 #define sfi2(n, m) scanf("%d%d", &n, &m) 22 #define pfi2(n, m) printf("%d %d\n", n, m) 23 #define pfi3(a, b, c) printf("%d %d %d\n", a, b, c) 24 #define MAXN 1000005 25 #define MOD 1000000007 26 const int INF = 0x3f3f3f3f; 27 ll inv[MAXN]; 28 ll quickpow(ll m, ll n) 29 { 30 ll ans = 1; 31 while(n) 32 { 33 if(n & 1)///如果n是奇数 34 ans = (ans * m) % MOD; 35 n = n >> 1;///位运算“右移1类似除2” 36 m = (m * m) % MOD; 37 } 38 return ans; 39 } 40 ll C(ll n, ll m) 41 { 42 if(m > n) return 0; 43 ll ans = 1; 44 for(int i = 1; i <= m; i++) 45 { 46 ll a = (n - m + i) % MOD; 47 ll b = i % MOD; 48 ans = ans * (a * quickpow(b, MOD - 2) % MOD) % MOD; 49 } 50 return ans; 51 } 52 ll Lucas(ll n, ll m) 53 { 54 if(m == 0) return 1; 55 else 56 return (C(n % MOD, m % MOD) * Lucas(n / MOD, m / MOD)) % MOD; 57 } 58 void get() 59 { 60 repu(i, 1, MAXN) 61 inv[i] = quickpow(i, MOD - 2); 62 } 63 ll cc[1010100]; 64 int main() 65 { 66 get(); 67 int T; 68 sfi(T); 69 int kase = 1; 70 ll n, m, k; 71 while(T--) 72 { 73 scanf("%lld%lld%lld", &n, &m, &k); 74 if(k==1) 75 { 76 printf("Case #%d: ",kase++); 77 if(n==1)printf("%d\n",m); 78 else printf("0\n"); 79 continue ; 80 } 81 ll cmk = Lucas(m, k); 82 ll t = quickpow(k - 1, n - 1); 83 t = (t * k) % MOD; 84 int flag = 0; 85 ll cc = 1; 86 for(ll p = k - 1; p >= 2; p--) 87 { 88 cc = (((cc * (p + 1)) % MOD) * inv[k - p]) % MOD; 89 ///手残多加了个MOD也是会TLE的。。。。 90 ll q = (((cc * p) % MOD) * quickpow(p - 1, n - 1)) % MOD; 91 if(flag) t = (t + q) % MOD; 92 else t = (t - q + MOD) % MOD; 93 flag = !flag; 94 } 95 printf("Case #%d: %lld\n", kase++, (t * cmk) % MOD); 96 } 97 return 0; 98 }
人生就像心电图,想要一帆风顺,除非game-over