zoukankan      html  css  js  c++  java
  • Gym 100548F Color 给花染色 容斥+组合数学+逆元 铜牌题

    Problem F. Color
    Description
    Recently, Mr. Big recieved n flowers from his fans. He wants to recolor those flowers with
    m colors. The flowers are put in a line. It is not allowed to color any adjacent flowers with
    the same color. Flowers i and i + 1 are said to be adjacent for every i, 1 ≤ i < n. Mr. Big
    also wants the total number of different colors of the n flowers being exactly k.
    Two ways are considered different if and only if there is at least one flower being colored
    with different colors.
    Input
    The first line of the input gives the number of test cases, T. T test cases follow. T is about
    300 and in most cases k is relatively small.
    For each test case, there will be one line, which contains three integers n, m, k (1 ≤ n, m ≤
    109
    , 1 ≤ k ≤ 106
    , k ≤ n, m).
    Output
    For each test case, output one line containing “Case #x: y”, where x is the test case
    number (starting from 1) and y is the number of ways of different coloring methods modulo
    109 + 7.
    Samples
    Sample Input Sample Output
    2
    3 2 2
    3 2 1
    Case #1: 2
    Case #2: 0

    题意:给你N朵花,M种颜料(n,m<=1e9),要求给所有花染色,且相邻的花不能用同样的颜色,求出最后恰好用了k种

    颜料的方案数(k<=1e5)

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <vector>
    #define MM(a,b) memset(a,b,sizeof(a));
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    #define CT continue
    #define SC scanf
    const int N=1e6+10;
    const int mod=1e9+7;
    int cas,n,m,k,kk;
    ll C[N],inv[N];
    
    ll _pow(ll a,ll b)
    {
        ll res=1;
        while(b){
            if(b&1) res=(res*a)%mod;
            a=(a*a)%mod;
            b>>=1;
        }
        return res;
    }
    
    void  init_yuan()
    {
       inv[1]=1;
       for(int i=2;i<=1e6;i++){
           inv[i]=(mod-mod/i)*inv[mod%i]%mod;
       }
    }//求逆元模板  
    
    void init_cki()
    {
        C[0]=1;
        for(int i=0;i<k;i++){
            C[i+1]=C[i]*(k-i)%mod*inv[i+1]%mod;
        }
    }//预处理C(k,i)
    
    ll c(ll m,ll k)
    {
        ll res=1;
        k=min(k,m-k);
        for(int i=0;i<k;i++){
            res=res*(m-i)%mod;
        }
        for(int i=0;i<k;i++){
            res=res*inv[i+1]%mod;
        }
        return res;
    }//求C(m,k)
    
    int main()
    {
        kk=0;
        init_yuan();
        SC("%d",&cas);
        while(cas--) {
            SC("%d%d%d",&n,&m,&k);
            init_cki();
            ll ans=k*_pow(k-1,n-1)%mod,res=0;
            for(int i=1;i<=k-2;i++) {
                if(i%2) res+=C[i]*(k-i)%mod*_pow(k-i-1,n-1)%mod;
                else res=(res-C[i]*(k-i)%mod*_pow(k-i-1,n-1)+mod)%mod;
            }
            ans=(ans-res+mod)%mod;
            ans=(ans*c(m,k))%mod;
            printf("Case #%d: %lld
    ",++kk,ans);
        }
        return 0;
    }
    

      错因分析:刚开始想的是直接在n上容斥,,果然是太过复杂,,,就挂了;;

    解答:1.可以转换下思路,,如果当前选了k种,那么涂完后花的颜色不超过k种的方案数为S=k*_pow(k-1,n-1),想象其是一个集合,设a[i](1<=i<=k)代表第i种颜料并没有用到,那么那么此情况下答案就为S-(a[1]并a[2]并...a[k])的面积,但是后面这个部分肯定是a[1]和a[2]等这些存在交集,所以就需要容斥了,最后因为存在C(m,k)种情况所以答案出来后还要乘C(m,k)

    2.除法取模需要用到逆元见资料

  • 相关阅读:
    springboot(十)使用LogBack作为日志组件
    springboot(九)文件上传
    django 安装
    macbook使用“终端”远程登录linux主机
    Mac 怎么通过自带终端连接linux服务器
    什么是变量?
    选择最好用的PyCharm IDE
    开发你的第一个Python程序
    Python介绍
    PyCharm 2017 安装教程
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5840630.html
Copyright © 2011-2022 走看看