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 }
View Code

 

posted @ 2015-09-03 21:39  一麻袋码的玛侬  阅读(160)  评论(0编辑  收藏  举报