题目:
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
-  0 0 4
-  0 1 3
-  0 2 2
-  0 3 1
-  0 4 0
-  1 0 3
-  1 1 2
-  1 2 1
-  1 3 0
-  2 0 2 
-  2 1 1 
-  2 2 0 
-  3 0 1 
-  3 1 0 
-  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
 4
4 3
3 5
1000 3
1000 5
Sample Output
 Case 1: 15
Case 2: 35
Case 3: 501501
Case 4: 84793457
分析与解答
b * k ≡ 1 (mod p) 是什么意思?
 就是(b*k)%p=1
 a mod b是什么意思?
 就是a%b
 这两个所有博客没人说,但是我不清楚。。
先看看什么是乘法逆元
当我们要求(a / b) mod p的值,且 a 很大,无法直接求得a / b的值时,我们就要用到乘法逆元。
满足 b * k ≡ 1 (mod p) 的 k 的值就是 b 关于 p 的乘法逆元。
我们可以通过求 b 关于 p 的乘法逆元 k,将 a 乘上 k 再模 p,即 (a * k) mod p。其结果与(a / b) mod p等价。
证:
 因为 b * k ≡ 1 (mod p)
 则有 b * k = p* x+1
 得到 k = (p * x + 1) / b
 将 k 代入(a * k) mod p
 得到:
 (a * (p * x + 1) / b) mod p
 =((a * p * x) / b + a / b) mod p
 =[((a * p * x) / b) mod p +(a / b)] mod p
 =[(p * (a * x) / b) mod p +(a / b)] mod p
 =(0 + (a / b)) mod p
 = (a/b) mod p
1.用欧几里得扩展求逆元
ax≡1(modp)
 可以等价的转化为ax−py=1 ,
 检查gcd(a,p)是否等于1 ,如果是的话
 套用exgcd解方程
 最后解出x即可
 求出来的x有可能为负数,所以结果进行变化:
 x = (x * (c/gcd) % b + b) % b; 即的a的乘法逆元的解x
void Euild(ll a, ll b, ll &x, ll &y)  
{if(0 == b){x = 1, y = 0;return ;}Euild(b, a%b, x, y);ll flag = x;x = y;y = flag - a/b * y;
}
2.用费马小定理
 费马小定理:假如p是质数,且gcd(a,p)=1,那么 a^(p-1)≡1(mod p)
 所以a*a^(p-2)≡1(mod p)
 那a^(p-2)就是a的乘法逆元
 可以利用快速幂计算
 2.1那看看什么是快速幂
 
3^7 = 3 * 3^2 * 3^4
 (7)10 = (111)2
 ———–4 2 1
 3^15 = 3 * 3^2 * 3^4 * 3^8
 (15)10 = (1111)2
 ———— 8 4 2 1
 3^5 = 3 * 3^2 * 3^4
 (5)10 = (101)2
 ———- 4 2 1
快速幂求x的y次方代码:
int pow_1(int x,int y){//x的y次方 int ren=x;int ans=1;while(y){if(y&1) ans*=ren;//取当前最末位的y,如果是1就继续乘ren ren*=ren;//下一位ren是当前ren的平方 1 2 4 8,这里8是x^4的平方,不是4的平方 y=y>>1;//y前进一位 }return ans;
} 
3.用递推法On求解
O(n)求1~n逆元表
 有时会遇到这样一种问题,
 在模质数p下,求1~n逆元 n< p
这个问题有种很牛的算法,其基于以下的推导:
 在求i的逆元时
 p%i+[p/i]i=p
 令a=p%i,b=[p/i],则有
 a+bi=p
 a+bi=0(mod p)
 bi=-a(mod p)
 i^-1=-b/a
 也就是说i的逆元为:-[p/i]*(p%i)^-1
 而p%i<i,那么可以从2递推到n求逆元,在求i之前p%i一定已经求出
 这样就可以O(n)求出所有逆元了
 (初始化 1^(-1)=1)
 代码如下
inv[1] = 1;  
for (int i = 2; i<MAXN; i++)  inv[i]=(long long)(p-p/i)*inv[p%i]%p;
好了现在我们再看这题
代码参考:
这题一个数拆成m个数相加,拆成的数可以是0,问有这m个数一共有几种情况,看成是n个小球放到m个盒子里。
 比如四个球放到三个盒子,盒子可以为空,怎么算的我实在不懂,先记住公式吧 方案数就是:C(n+m-1,m-1)
 组合数公式:
 约定f(a)代表a的阶乘, C(m,n) = f(m)/(f(n)*f(m-n));
 在本题就是C(n+m-1,m-1) = f(n+m-1)/(f(m-1)f(n));
 本题代码实现:
 我们打表用数组存一个数的阶乘,
 f(m)/(f(n) * f(m-n))%mod=(f(m)/f(n))%mod * (1/f(m-n))%mod
 =f(m) * quick(f(m-1),mod-2) % mod quick(f(n),mod-2) % mod
 a[n+k-1]quick(c,mod-2)%modquick(d,mod-2)%mod
#include <bits/stdc++.h>
#define mod 1000000007
#define ll long long
using namespace std;
ll a[2000000];
void C()//阶乘打表 
{memset(a,0,sizeof(a));a[0] = a[1] = 1 ;for(int i = 2 ; i <=2000000;i++)a[i] = a[i-1]*i%mod;
}
ll quick(ll a , ll b)//快速幂取模 
{ll res = 1 ;while(b){if(b&1) res = res *  a %mod ;b>>=1;a = a * a %mod ;}return res ;
}
int main()
{int t ;cin>>t;C();for(int cas = 1 ; cas<=t;cas++){ll n , k ;cin>>n>>k;ll c = a[k-1];ll d = a[n];printf("Case %d: ",cas);cout<<a[n+k-1]*quick(c,mod-2)%mod*quick(d,mod-2)%mod<<endl;}return 0;
}现在做一下推广
我们组合数求模的板子
/*
mod=1e6+3
样例输入方式:
3
4 2
5 0
6 4
*/
//这里直接求出C(M,N)%mod#include<cstdio>  
#include<cstring>  
#include<algorithm>  
#include<iostream>  
#include<cmath>  using namespace std;  
const int INF=0x3f3f3f3f;  
typedef long long LL;  
const int mod=1e6+3;  
const int maxn=1e6+100;  
LL fac[maxn],inv[maxn];  
LL Pow(LL a,LL b)  
{  LL ans=1;  while(b)  {  if(b&1)  ans=(ans*a)%mod;  a=(a*a)%mod;  b>>=1;  }  return ans;  
}  
int main()  
{  int cas=0;  int n,a,b;  fac[0]=1; //inv[0]=for(int i=1;i<=1000000;i++)  {  fac[i]=(fac[i-1]*i)%mod; //对阶乘打表 //   inv[i]=Pow(fac[i],mod-2);  }  scanf("%d",&n);  while(n--)  {  scanf("%d%d",&a,&b);  long long c=Pow(fac[b],mod-2); long long d=Pow(fac[a-b],mod-2); LL ans=fac[a]*c%mod*d%mod;  printf("Case %d: %lld\n",++cas,ans);  }  return 0;  
}