首页 > 代码库 > (light oj 1102) Problem Makes Problem (组合数 + 乘法逆元)

(light oj 1102) Problem Makes Problem (组合数 + 乘法逆元)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1102

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 dont 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个数的方案数.

分析:显然这个就是一个组合公式,隔板法。可以把问题转化为x1+x2+…..xk = n 这个多元一次方程上。然后这个解就是C(n+k-1,k-1) 
这道题n,k范围都是1e6。 
我们可以预处理出阶乘,然后求对应的组合数,注意这里需要取Mod,用下逆元就好啦.

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include <map>
#include <string>
#include <vector>
#include<iostream>
using namespace std;
#define N 3000006
#define INF 0x3f3f3f3f
#define LL long long
#define mod 1000000007
LL arr[N];
void Init()
{
    arr[0] = 1;
    for(int i=1;i<=N;i++)
    {
        arr[i] = (arr[i-1]*i)%mod;
        arr[i] %= mod;
    }
}
LL quick(LL a, LL b)
{
    a = a%mod;
    LL ans = 1;
    while(b)
    {
        if(b&1)
            ans = ans*a%mod;
        a = a*a%mod;
        b /= 2;
    }
    return ans %mod;
}
LL solve(LL a, LL b, LL c)
{
    if(b>a)
        return 0;
    return arr[a] * (quick(arr[b] * arr[a-b],c-2)) %mod;///利用乘法逆元
}
int main()
{
    Init();
    int T;
    int con=1;
    scanf("%d",&T);
    while(T--)
    {
        LL n,k;
        scanf("%lld %lld",&n,&k);
        printf("Case %d: %lld\n",con++,solve(n+k-1,k-1,mod));///Cn-k+1(k-1);
    }
    return 0;
}

 

(light oj 1102) Problem Makes Problem (组合数 + 乘法逆元)