Codeforces Gym 100548F Color (组合数+容斥)
2017-10-13 20:04
267 查看
Color
Description
Recently, Mr. Bigrecieved n flowers from his fans. He wants to recolor those flowerswith m colors. The flowers are put in a line. It is not allowed tocolor any adjacent flowers with the same color. Flowers i and i + 1are said to be adjacent for every i, 1 ≤
i < n. Mr. Big alsowants the total number of different colors of the n flowers beingexactly k.
Two ways areconsidered different if and only if there is at least one flowerbeing colored
with differentcolors.
Input
The first line ofthe input gives the number of test cases, T. T test cases follow. Tis 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 ≤ 10^9, 1 ≤ k ≤ 10^6, k ≤ n, m).
Output
For each test case,output one line containing “Case #x: y”, where x is the test casenumber (starting from 1) and y is the number of ways of differentcoloring methods modulo 10^9 + 7.
Samples
题目链接:http://codeforces.com/gym/100548/attachments
题目大意:给一条直线上的n个物品染色,给你m种颜色,要求恰好使用k种颜色的方案数。(相邻位置颜色不能相同)
思路:首先知道从m种颜色中选取k种方案数为C(m,k)很容易知道最多使用k种颜色的方案数为k*(k-1)^n-1(这里可以这样理解,第n个位置有k种染法,剩下k-1种颜色染n-1个位置方案数(k-1)^n-1
但是要求的是恰好为k种的方案数,因此要容斥一下,容斥可以这样理解,假设不超过i种的方案数为f[i],那么其中包括了不超过i-1种的,不超过i-1种的里面又包含了不超过i-2种的,以此类推得到ans = f[k] - (f[k - 1] - (f[k - 2] - (... - (f[3] - f[2])))) = f[k] - f[k - 1] + f[k - 2] - ... + (-1)^(k - i)f[i](结合这里就很容易理解容斥了)
因此最后答案为C(m,k)(Σ(-1)^(k - i)f[i]),其中f[i] = C(k,i)i*(i-1)^(n-1),特殊处理一下n!=1且k=1时候情况为0,还有就是注意一下中间过程可能为负数情况,需要+mod再%mod;
当然,下面代码写的是这种写法,还有一种写法直接给出公式了:ans=C(m,k)(Σ(-1)^(i)f[i]),其中f[i]=C(k,i)(k-i)*(k-i-1)^(n-1);
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9 + 7;
const int maxn = 1e6 + 5;
LL sum1[maxn],sum11[maxn];
LL inv[maxn],C[maxn];
LL n, m, k,pri[maxn],ni[maxn];
LL poww(LL a, LL k, LL s)
{
LL ans = 1;
while(k)
{
if(k & 1)ans = ans * a % s;
a = a * a % s;
k /= 2;
}
return ans;
}
void niyuan()
{
inv[1]=1;
for(int i=2;i<maxn;i++)
{
inv[i] = (mod - mod/i) * inv[mod%i] % mod;
}
}
void init() //打表
{
pri[0]=1;
ni[0]=1;
for (int i=1;i<maxn ;i++)
{
pri[i]=pri[i-1]*i%mod; //N!
ni[i]=poww(pri[i],mod-2,mod);
}
}
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()
{
int T;
niyuan();
init();
scanf("%d",&T);
while(T--)
{
static int t = 1;
scanf("%lld%lld%lld", &n, &m, &k);
if(n != 1 && k == 1)
{
printf("Case #%d: 0\n",t++);
continue;
}
LL sum = c(m, k); //Cmk
LL ans = 0, sum3;
for(LL i = 0; i <= k; i++) sum1[i] = 0;
for(LL i = 0; i <= k; i++)
{
LL sum=((pri[k]*ni[i]%mod)*ni[k-i])%mod;//C(k,i)
sum1[i]=sum;
}
for(LL i = 0; i <= k; i++) sum11[i] = (poww(i - 1, n - 1, mod) + mod) % mod;
for(LL i = 0; i <= k; i++)
{
LL sum2 = sum11[i];
sum2 = (sum2 * i + mod) % mod;
if((k-i) & 1) sum3 = -1;
else sum3 = 1;
sum1[i] = (sum1[i] * sum2 + mod) % mod;
sum1[i] = (sum1[i] * sum3 + mod) % mod;
ans = (ans + sum1[i]) % mod;
}
ans = (ans * sum) % mod;
printf("Case #%d: %lld\n", t++, ans);
}
return 0;
}
Description
Recently, Mr. Bigrecieved n flowers from his fans. He wants to recolor those flowerswith m colors. The flowers are put in a line. It is not allowed tocolor any adjacent flowers with the same color. Flowers i and i + 1are said to be adjacent for every i, 1 ≤
i < n. Mr. Big alsowants the total number of different colors of the n flowers beingexactly k.
Two ways areconsidered different if and only if there is at least one flowerbeing colored
with differentcolors.
Input
The first line ofthe input gives the number of test cases, T. T test cases follow. Tis 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 ≤ 10^9, 1 ≤ k ≤ 10^6, k ≤ n, m).
Output
For each test case,output one line containing “Case #x: y”, where x is the test casenumber (starting from 1) and y is the number of ways of differentcoloring methods modulo 10^9 + 7.
Samples
Sample Input | Sample Output |
2 3 2 2 3 2 1 | Case #1: 2 Case #2: 0 |
题目大意:给一条直线上的n个物品染色,给你m种颜色,要求恰好使用k种颜色的方案数。(相邻位置颜色不能相同)
思路:首先知道从m种颜色中选取k种方案数为C(m,k)很容易知道最多使用k种颜色的方案数为k*(k-1)^n-1(这里可以这样理解,第n个位置有k种染法,剩下k-1种颜色染n-1个位置方案数(k-1)^n-1
但是要求的是恰好为k种的方案数,因此要容斥一下,容斥可以这样理解,假设不超过i种的方案数为f[i],那么其中包括了不超过i-1种的,不超过i-1种的里面又包含了不超过i-2种的,以此类推得到ans = f[k] - (f[k - 1] - (f[k - 2] - (... - (f[3] - f[2])))) = f[k] - f[k - 1] + f[k - 2] - ... + (-1)^(k - i)f[i](结合这里就很容易理解容斥了)
因此最后答案为C(m,k)(Σ(-1)^(k - i)f[i]),其中f[i] = C(k,i)i*(i-1)^(n-1),特殊处理一下n!=1且k=1时候情况为0,还有就是注意一下中间过程可能为负数情况,需要+mod再%mod;
当然,下面代码写的是这种写法,还有一种写法直接给出公式了:ans=C(m,k)(Σ(-1)^(i)f[i]),其中f[i]=C(k,i)(k-i)*(k-i-1)^(n-1);
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9 + 7;
const int maxn = 1e6 + 5;
LL sum1[maxn],sum11[maxn];
LL inv[maxn],C[maxn];
LL n, m, k,pri[maxn],ni[maxn];
LL poww(LL a, LL k, LL s)
{
LL ans = 1;
while(k)
{
if(k & 1)ans = ans * a % s;
a = a * a % s;
k /= 2;
}
return ans;
}
void niyuan()
{
inv[1]=1;
for(int i=2;i<maxn;i++)
{
inv[i] = (mod - mod/i) * inv[mod%i] % mod;
}
}
void init() //打表
{
pri[0]=1;
ni[0]=1;
for (int i=1;i<maxn ;i++)
{
pri[i]=pri[i-1]*i%mod; //N!
ni[i]=poww(pri[i],mod-2,mod);
}
}
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()
{
int T;
niyuan();
init();
scanf("%d",&T);
while(T--)
{
static int t = 1;
scanf("%lld%lld%lld", &n, &m, &k);
if(n != 1 && k == 1)
{
printf("Case #%d: 0\n",t++);
continue;
}
LL sum = c(m, k); //Cmk
LL ans = 0, sum3;
for(LL i = 0; i <= k; i++) sum1[i] = 0;
for(LL i = 0; i <= k; i++)
{
LL sum=((pri[k]*ni[i]%mod)*ni[k-i])%mod;//C(k,i)
sum1[i]=sum;
}
for(LL i = 0; i <= k; i++) sum11[i] = (poww(i - 1, n - 1, mod) + mod) % mod;
for(LL i = 0; i <= k; i++)
{
LL sum2 = sum11[i];
sum2 = (sum2 * i + mod) % mod;
if((k-i) & 1) sum3 = -1;
else sum3 = 1;
sum1[i] = (sum1[i] * sum2 + mod) % mod;
sum1[i] = (sum1[i] * sum3 + mod) % mod;
ans = (ans + sum1[i]) % mod;
}
ans = (ans * sum) % mod;
printf("Case #%d: %lld\n", t++, ans);
}
return 0;
}
相关文章推荐
- Codeforces Gym 100548F Color (组合数+容斥)
- cf/Codeforces Gym 100548F Color (容斥原理)
- cf/Codeforces Gym 100548F Color (2014年西安站F题) (容斥原理)
- Codeforces Gym 100286J Javanese Cryptoanalysis 傻逼暴力
- 【Codeforces Gym 100187A】
- Codeforces Gym 100203H Highways 最小生成树
- codeforces Gym 100971 A、B、C、F、G、K、L
- codeforces Gym 100338F Spam Filter 垃圾邮件过滤器(模拟,实现)
- Codeforces GYM 100962J: Jimi Hendrix 题解
- Codeforces Gym 100733A Shitália 计算几何
- Codeforces Gym 100231B Intervals 线段树+二分+贪心
- codeforces gym 100345I Segment Transformations [想法题]
- codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点
- Codeforces Gym 100340C ePig 模拟
- Codeforces Gym 101473D Folding Machine DFS/XJBS
- CodeForces Gym 101741 简要题解
- codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径
- codeforces Gym 101341 K Competitions
- codeforces gym 100645A
- CodeForces Gym 100989H Queue (A)