As I am fond of making easier problems, I discovered a problem. Actually, the problem is 'how can you make n by adding k non-negative integers?' I think a small example will make things clear. Suppose n=4 and k=3. There are 15 solutions. They are
1. 0 0 4
2. 0 1 3
3. 0 2 2
4. 0 3 1
5. 0 4 0
6. 1 0 3
7. 1 1 2
8. 1 2 1
9. 1 3 0
10. 2 0 2
11. 2 1 1
12. 2 2 0
13. 3 0 1
14. 3 1 0
15. 4 0 0
As I have already told you that I use to make problems easier, so, you don't have to find the actual result. You should report the result modulo 1000,000,007.
Input
Input starts with an integer T (≤ 25000), denoting the number of test cases.
Each case contains two integer n (0 ≤ n ≤ 106) and k (1 ≤ k ≤ 106).
Output
For each case, print the case number and the result modulo 1000000007.
Sample Input |
Output for Sample Input |
|
4 4 3 3 5 1000 3 1000 5 |
Case 1: 15 Case 2: 35 Case 3: 501501 Case 4: 84793457 |
题意是给你一个数n,让你把它分成非负的k份。
就是方程n=x1+x2+x3+...+xk非负解的个数。可以看成把n+k分成k份,然后分出来的k个每个再减1,这样就可以用隔板法用k-1个板隔成k份,就是C(n+k-1,k-1)。
接下来主要就是求组合数了。C(a,b)% p = f[a]/(f[a-b]*f[b]) % p(f[]是阶乘)
因为除法不能取模,所以要利用乘法逆元。
这里可以直接求乘法逆元(用拓展欧几里得)
也可以用费马小定理:ap-1==1mod(p),所以逆元a-1==ap-2mod(p),然后用快速幂求出来就可以了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define mod 1000000007
using namespace std;
LL f[2000010];
void init()
{
f[0] = 1;
for(int i=1;i<=2000000;i++)
f[i] = f[i-1]*i%mod;
}
LL quickpow(LL x,int n)
{
LL res = 1;
while(n > 0)
{
if(n&1)
res = res*x%mod;
x = x*x%mod;
n >>= 1;
}
return res;
}
int main(void)
{
int T,n,k;
init();
scanf("%d",&T);
int cas = 1;
while(T--)
{
scanf("%d%d",&n,&k);
LL ans = quickpow(f[n]*f[k-1]%mod,mod-2);
ans = ans*f[n+k-1]%mod;
printf("Case %d: %lld\n",cas++,ans);
}
return 0;
}

本文介绍了一个关于非负整数分拆的问题,并提供了一种高效的算法解决方案。问题的核心在于计算将一个非负整数n分为k个非负整数之和的方法数量,并通过模运算处理大数值。文章给出了具体的实现思路,包括使用组合数学中的隔板法和快速幂计算阶乘的乘法逆元。
770

被折叠的 条评论
为什么被折叠?



