Uva 7040 color(组合数)

题意:n个球有m种颜色可选,使用k种不同的颜色,求方案数;

思路:Cm[k]表示m中选k,方案数为Cm[k]*(k*(k-1)^(n-1)-sigma(p*(p-1)^(n-1))(1<=p<k));

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MOD 1000000007
int t,n,m,k;
long long ck[5000100],cm[5000010];
long long inv[5000100];
long long ans;
void init(){  //预处理逆元
  inv[1]=1;
  for(int i=2;i<=1000100;i++){
    inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
  }
}
long long pow(long long a,long long b){  //快速幂
    long long res=1,temp=a;
    if(b==0) return 1;
    if(b==1) return a;
    while(b){
        if(b&1) res=res*temp%MOD;
        temp=temp*temp%MOD;
        b/=2;
    }
    return res;
}
void combine(){  //组合数
   ck[0]=cm[0]=1;
   for(int i=1;i<=k;i++){
     ck[i]=ck[i-1]%MOD*(k-i+1)%MOD*inv[i]%MOD;
     cm[i]=cm[i-1]%MOD*(m-i+1)%MOD*inv[i]%MOD;
   }
}
int main()
{
    int i,j,cas,flag;
    init();
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++){
        scanf("%d%d%d",&n,&m,&k);
        printf("Case #%d: ",cas);
        combine();
        ans=0;flag=1;
        for(i=k;i>=1;i--){
            if(flag){
                ans=((ans+ck[i]*i%MOD*pow(i-1,n-1)%MOD)%MOD+MOD)%MOD;//取模不准确也会wa
            }
            else{
                ans=((ans-ck[i]*i%MOD*pow(i-1,n-1)%MOD)%MOD+MOD)%MOD;
            }
            flag=1-flag;
        }
        ans=ans*cm[k]%MOD;
        printf("%lld\n",ans);
    }
    return 0;
}
时间: 2024-10-09 22:43:23

Uva 7040 color(组合数)的相关文章

uva 1625 - Color Length(dp 里面 L C S 问题解决方式变形)

LCS属线性结构上的动态规划,应该是动规里面很简单的一种类型. 最长公共子序列问题,一旦明确了状态,找到状态转移方程还是很简单的.但是对于本题来说,难点之一就是会很难想到该如何定义状态. 作为一只菜鸟,兹认为此题很复杂. 首先我是想不到每一步都把没到终点的字母全加上1,以及这种效果与你去找开始和结束的效果是一样的. 甚至,若不是在做动规的专题,我根本想不到这样的题目,会用动规来解决. 再一个,我想不到状态可以这么来定义"设d[ i ][ j ]表示两个序列分别已经拿出去了 i 个和 j 个元素

UVALive 7040 Color (容斥原理+逆元+组合数+费马小定理+快速幂)

题目:传送门. 题意:t组数据,每组给定n,m,k.有n个格子,m种颜色,要求把每个格子涂上颜色且正好适用k种颜色且相邻的格子颜色不同,求一共有多少种方案,结果对1e9+7取余. 题解: 首先可以将m 与后面的讨论分离.从m 种颜色中取出k 种颜色涂色,取色部分有C(m, k) 种情况: 然后通过尝试可以发现,第一个有k种选择,第二个因不能与第一个相同,只有(k-1) 种选择,第三个也只需与第二个不同,也有(k-1) 种选择.总的情况数为k ×(k-1)^(n-1).但这仅保证了相邻颜色不同,总

组合数+容斥原理 UVALive 7040 Color(14西安F)

题目传送门 题意:n盆花涂色,相邻不能涂相同的颜色,从m中颜色选取k种颜色涂,保证正好有k种颜色 分析:从m中颜色选取k种就是C (m, k),然后第一个有k种选择,之后的都有k-1种选择,这样是不超过k种颜色的方案,那么减去少了Ai颜色的方案数,用容斥原理,最后答案是C(m,k) × ( k × (k-1)^(n-1) + ∑((-1)^p × C(k, p) × p × (p-1)^(n-1) ) (2 <= p <= k-1): #include <cstdio> #incl

UVA 1625 Color Length DP

题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4500 题目描述: 两个字符串 ,组成一个新的字符串, 每次只能从其中一个的开头选一个加到新的尾, 问l(i)的最小值 解题思路: dp(i, j)  表示从第一个字符串中取i 个, 第二个字符串中取j个时的最优方案, 我们创建数组c 表示从第一个字符串中取i 个, 第二个字符串

Codeforces 100548F - Color (组合数+容斥)

题目链接:http://codeforces.com/gym/100548/attachments 有n个物品 m种颜色,要求你只用k种颜色,且相邻物品的颜色不能相同,问你有多少种方案. 从m种颜色选k种颜色有C(m, k)种方案,对于k种颜色方案为k*(k-1)^(n-1)种.但是C(m, k)*k*(k-1)^(n-1)方案包括了选k-1,k-2...,2种方案. 题目要求刚好k种颜色,所以这里想到用容斥. 但是要是直接C(m, k)*k*(k-1)^(n-1) - C(m, k-1)*(k

UVa 1625 Color Length

思路还算明白,不过要落实到代码上还真敲不出来. 题意: 有两个由大写字母组成的颜色序列,将它们合并成一个序列:每次可以把其中一个序列开头的颜色放到新序列的尾部. 对于每种颜色,其跨度定义为合并后的序列中最后一次和第一次出现的位置之差,求所有合并方案中所有颜色跨度之和的最小值. 分析: d(i, j)表示两个串分别已经移走了i个和j个字符.那么无论新串的顺序是什么,有多少种颜色已经开始但尚未结束是确定的,记为c(i, j).再继续移走一个字符,所有颜色跨度之和就增加c(i, j).c的计算是通过记

UVA 1625 Color Length 颜色的长度

dp[i][j]表示前一个序列拿了i个颜色,后一个序列拿了j个颜色的最小花费. 转移的时候显然只能向dp[i+1][j],或dp[i][j+1]转移,每增加拿走一个颜色,之前已经出现但没结束的颜色个数的跨度都增加1,为了在转移的时候快速算出这个值,先预处理出每个颜色在各个序列中的起始和终止位置. memset (dp),然后就GG了 #include<bits/stdc++.h> using namespace std; #define FOR(i,s,e) for(int i = s; i

UVA 1625 Color Length (DP)

题意:见紫书P276 思路:(设一个颜色序列为s1,另一个为s2)要把最优子结构找到是关键,状态就是天然的执行步骤,d(i,j)表示s1移走了i个元素 s2移走了j个元素的状态.下一步只有两个决策,决策后的剩余的问题和原问题一样,这就是最优子结构.所以每次决策时要保证决策的产生的花费+子问题的解达到最优 所以状态方程显然:dp[i][j]=min(dp[i+1][j],dp[i][j+1])+res[i][j] 本题的难点在于求res[i][j],所以要在之前对字符串做预处理 代码: //0 K

UVA - 1205 Color a Tree

大意就是给你一颗树,每个点有一个权值w[i],求一个排列使得 所有的父亲都在儿子前面 并且排列的权值最小. 排列的权值在这里定义为 Σ i * w[p[i]]   ,其中p[i] 是排列第i个位置的元素. 然后我瞎jb胡了一个算法,对于每个子树维护一个 p[],表示只考虑子树内的元素的最优排列.显然我们只要把一个点的所有儿子都合并之后再把这个点放在排列的第一个位置就可以了.(可以证明这些元素再往上走的时候相对位置还是一样的) 问题是怎么合并. 其实这就是个dp,合并x和y子树的时候,f[i][j