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.除法取模需要用到逆元见资料

  • 相关阅读:
    在ASP.NET 2.0中使用WebParts
    Asp.net生成静态页面原理
    提高ASP.Net应用程序性能的十大方法
    Web2.0之Tag标签原理实现浅析
    ASP.NET 2.0中的URL映射
    动态加载控件UserControl到页面上:视图状态问题
    C#自动登录网页浏览页面 抓取数据
    .NET Framework 类库提供的命名空间
    一个用于热部署的框架设想
    重构如何进行?
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5840630.html
Copyright © 2011-2022 走看看