lightoj 1102 - Problem Makes Problem
1102 - Problem Makes Problem
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=4and 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 |
http://www2.chinaedu.com/101resource004/wenjianku/200501/101ktb/lanmu/XF1S0213/XF1S0213.htm
隔板法
思路:组合数学,费马小定理求逆元,快速幂。
用隔板法来求,这个问题可以转化为x1+x2+...xk=n的多元方不同程解的个数,并且xk〉=0;
就是组合数C(n+k-1,k-1) ,那么由费马小定理ap-1==1mod(p);设a-1为a的逆元则(a*a-1*ap-2)=a-1mod(p);
即ap-2=a-1mod(p);C(a,b) =(f(a))/(f(b)*f(a-b));
C(a,b)%p=((f(a))/(f(b)*f(a-b)))%P;其中f(n)表示阶乘。
(a/b)%p=k%p;两边同乘b ----a%p=(k*b)%p;然后两边同乘b-1%p;----a*b-1%p=k%p;
而根据费马小定理ap-2=a-1mod(p);用快速幂求下bp-2%p就可以了。
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<string.h> 5 #include<math.h> 6 #include<queue> 7 using namespace std; 8 const long long N=1e9+7; 9 typedef long long LL; 10 LL quickmi(long long a,long long b); 11 LL DP[2*1000005]; 12 void Init() 13 { 14 int i,j; 15 DP[0]=1; 16 for(i=1;i<=2000005;i++) 17 { 18 DP[i]=(DP[i-1]*i)%N; 19 } 20 } 21 int main(void) 22 {Init(); 23 int i,j,k,p,q; 24 scanf("%d",&k); 25 for(i=1;i<=k;i++) 26 { 27 scanf("%d %d",&p,&q); 28 LL ans=quickmi(DP[q-1]*DP[p]%N,N-2); 29 printf("Case %d: ",i); 30 printf("%lld\n",DP[p+q-1]*ans%N); 31 } 32 return 0; 33 } 34 35 LL quickmi(long long a,long long b) 36 { 37 LL sum=1; 38 while(b) 39 { 40 if(b&1) 41 sum=(sum*a)%(N); 42 a=(a*a)%N; 43 b/=2; 44 } 45 return sum; 46 }