zoukankan      html  css  js  c++  java
  • UVALive 7040 Color

    题目链接:LA-7040

    题意为用m种颜色给n个格子染色。问正好使用k种颜色的方案有多少。

    首先很容易想到的是( k * (k-1)^{n-1}),这个算出来的是使用小于等于k种颜色给n个方格染色的方案数。

    我们希望求得的是使用正好k种颜色给n个方格染色的方案数,简单的想法是,直接减去小于等于k-1种颜色的方案数。

    但是,要计算使用小于等于k-1种颜色染色的方案数,不能直接减去(C_{k}^{k-1} * (k-1) * (k-2)^{n-1}),原因是会有重复的部分。

    我们用(S_{k})表示使用小于等于k种颜色给n个格子染色的方案数。

    则我们希望求出的答案可以用(C_m^k * (S_k- igcup _{i=1} ^ {C_k^{k-1}} S_{k-1}))来表示。

    于是问题变成了求( igcup _{i=1} ^ {C_k^{k-1}} S_{k-1}),因为有重复,自然而然的我们想到容斥原理。

    仔细思考后(或者列表格),发现所有(S_{k-1})两两相交的并等于(S_{k-2}),所有(S_{k-1})三三相交的并等于(S_{k-3}),以此类推,减加减加即可。

    代码如下:

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<algorithm>
     5 #include<set>
     6 #include<cmath>
     7 using namespace std;
     8 typedef long long LL;
     9 const LL MAXK=1000000;
    10 const LL MOD=1e9+7;
    11 
    12 LL CM[MAXK+10],CK[MAXK+10],inv[MAXK+10];
    13 LL extgcd(LL a,LL b,LL &x,LL &y)
    14 {
    15     LL d=a;
    16     if(b!=0)
    17     {
    18         d=extgcd(b,a%b,y,x);
    19         y-=(a/b)*x;
    20     }
    21     else { x=1; y=0; }
    22     return d;
    23 }
    24 //快速幂
    25 //求x^n%mod
    26 LL powMod(LL x,LL n,LL mod)
    27 {
    28     LL res=1;
    29     while(n>0)
    30     {
    31         if(n&1) res=res*x % mod;
    32         x=x*x % mod;
    33         n>>=1;
    34     }
    35     return res;
    36 }
    37 //求逆元
    38 //a和m应该互质
    39 LL modInverse(LL a,LL m)
    40 {
    41     LL x,y;
    42     extgcd(a,m,x,y);
    43     return (m+x%m)%m;
    44 }
    45 LL n,m,k;
    46 void init()
    47 {
    48     CM[0]=1;
    49     for(LL i=0;i<=k-1;i++)
    50         CM[i+1]=CM[i]*(m-i) %MOD *inv[i+1] % MOD;
    51     CK[0]=1;
    52     for(LL i=0;i<=k-1;i++)
    53         CK[i+1]=CK[i]*(k-i) %MOD *inv[i+1] % MOD;
    54 }
    55 LL f(LL n,LL k)
    56 {
    57     LL ans = 0;
    58     LL flag=1;
    59     for(LL i=k;i>=1;i--)
    60     {
    61         ans = (flag * CK[i] % MOD * i % MOD * powMod(i-1,n-1,MOD) % MOD +ans + MOD ) % MOD;
    62         flag*=-1;
    63     }
    64     ans = ans*CM[k]%MOD;
    65     return ans;
    66 }
    67 int main()
    68 {
    69 #ifdef LOCAL
    70     freopen("in.txt","r",stdin);
    71     // freopen("out.txt","w",stdout);
    72 #endif
    73     for(LL i=1;i<=MAXK;i++) inv[i]=modInverse(i,MOD);
    74     LL t;
    75     scanf("%lld",&t);
    76     for(LL tt=1;tt<=t;tt++)
    77     {
    78         scanf("%lld%lld%lld",&n,&m,&k);
    79         init();
    80         printf("Case #%lld: %lld
    ",tt,f(n,k)%MOD);
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    git的优秀教程
    线性表的顺序存储结构和链式存储结构的比较
    python3基础知识学习记录
    thinkPHP为什么设置一个单入口文件?
    2017年读过的专业书
    DFS(深度优先搜索)模板
    HDOJ2553-N皇后问题(DFS)
    POJ(2784)Buy or Build
    并查集 分类: 并查集 2015-07-09 16:32 0人阅读 评论(0) 收藏
    Number of Containers(数学) 分类: 数学 2015-07-07 23:42 1人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/zarth/p/6623433.html
Copyright © 2011-2022 走看看