• Gym100548F Color


    题目链接:https://vjudge.net/problem/Gym-100548F

    题目大意:

      n 朵花,按顺序排成一排。从 m 种颜色中选出 k 种颜色,给这 n 朵花染色,要求相邻的花颜色不同。问共有多少种染色方案?

      ((1 le n,m le 10^{9}, 1 le k le 10^{6}, k le n,m))

    知识点:  快速幂算法、组合数、容斥原理、逆元。

    解题思路:

      第一步:从 m 种颜色中选出 k 种颜色,方案数:(C_m^k);

      第二步:将这 k 种颜色合理地安排到每一朵花上,要求每一种颜色都有用到,而且相邻的花颜色不同。在此我们设 (G(x)) 为将 x 种颜色合理地安排到每一朵花上,只要求相邻的花颜色不同,不要求每一种颜色都有用到。则 ( G(x) = x(x-1)^{n-1}) 。根据容斥原理,我们可得第二步的方案数为:

      ( C_{k}^{k}G(k) - C_{k}^{k-1}G(k-1) + ... +(-1)^{k-2}G(2));

      则总的方案数为:

      (C_m^k imes[C_{k}^{k}G(k) - C_{k}^{k-1}G(k-1) + ... +(-1)^{k-2}G(2)])

      (=C_m^k imes[C_{k}^{k}k(k-1)^{n-1} - C_{k}^{k-1}(k-1)(k-2)^{n-1} + ... +(-1)^{k-2} imes2]).

    AC代码:

     1 #include<cstdio>
     2 using namespace std;
     3 typedef long long ll;
     4 const ll mod = 1e9 + 7;
     5 const int maxn = 1e6 + 5;
     6 ll inv[maxn], C_k[maxn];
     7 
     8 ll exp_mod(ll a, ll b) {    //快速幂求a^b%mod
     9     ll ret = 1;
    10     while (b) {
    11         if (b & 1) ret = (ret*a) % mod;
    12         a = (a*a) % mod;
    13         b >>= 1;
    14     }return ret;
    15 }
    16 void init() {            //逆元表
    17     inv[1] = 1;
    18     for (int i = 2; i<maxn; i++)
    19         inv[i] = exp_mod((ll)i, mod - 2) % mod;
    20 }
    21 void find_Ck(ll k) {    //求出C(K, 0,1,...k)
    22     C_k[0] = 1;
    23     for (ll i = 1; i <= k; i++) {
    24         C_k[i] = ((C_k[i - 1] * (k - i + 1) % mod)*inv[i]) % mod;
    25     }
    26 }
    27 int main() {
    28     //    freopen("in.txt","r",stdin);
    29     init();
    30     int T;
    31     ll n, m, k;
    32     scanf("%d", &T);
    33     for (int t = 1; t <= T; t++) {
    34         scanf("%lld%lld%lld", &n, &m, &k);
    35         find_Ck(k);
    36         ll ans1 = 0;
    37         ll sign = 1;
    38         for (ll i = k; i >= 1; i--, sign = -sign)        //求C(k,k)*k*(k-1)^(n-1) - C(k,k-1)*(k-1)*(k-2)^(n-1) ......
    39             ans1 = (ans1 + ((C_k[i] * i%mod)*exp_mod(i - 1, n - 1) % mod)*sign + mod) % mod;
    40         ll ans2 = 1;
    41         for (ll i = 1; i <= k; i++) {    //C(m,k)
    42             ans2 = (ans2*(m - i + 1) % mod)*inv[i] % mod;    //注意除法取余运算要用逆元
    43         }
    44         printf("Case #%d: %lld
    ", t, ans1*ans2%mod);
    45     }
    46     return 0;
    47 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    第八次作业 8、特征选择
    第六次作业 6.逻辑归回
    MySQL5.7详细配置教程
    MySQL5.1安装与卸载教程
    常用的正则表达式
    MongoDB安装以及配置教程
    机器学习:4.K均值算法--应用
    利用Python制作二维码
    机器学习:15 手写数字识别-小数据集
    机器学习:14 深度学习-卷积
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/7830087.html
Copyright © 2020-2023  润新知