• 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)
    21 #define sfi2(n, m) scanf("%d%d", &n, &m)
    22 #define pfi2(n, m) printf("%d %d
    ", n, m)
    23 #define pfi3(a, b, c) printf("%d %d %d
    ", 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
    ",m);
    78             else printf("0
    ");
    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
    ", kase++, (t * cmk) % MOD);
    96     }
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    Django错误笔记1
    Django学习笔记1 启动及配置一个Django项目
    ubuntu 安装mysqldb
    二叉树 总结
    序列二叉树和反序列 (不是自己做的)
    二叉树的路径
    二叉搜索树的后续遍历
    二叉树层序遍历
    栈的压入 弹出序列
    包含 min的栈
  • 原文地址:https://www.cnblogs.com/ACMERY/p/4780773.html
Copyright © 2020-2023  润新知