题目:

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
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+b
i=p
a+bi=0(mod p)
b
i=-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;
}

(组合数求模=乘法逆元+快速幂) Problem Makes Problem相关推荐

  1. 数学--数论--HDU 4675 GCD of Sequence(莫比乌斯反演+卢卡斯定理求组合数+乘法逆元+快速幂取模)

    先放知识点: 莫比乌斯反演 卢卡斯定理求组合数 乘法逆元 快速幂取模 GCD of Sequence Alice is playing a game with Bob. Alice shows N i ...

  2. 阿里云 超级码力在线编程大赛初赛 第2场 题目4. 小栖的金字塔(超级卡特兰数+除法求模/乘法逆元)

    文章目录 1. 题目 2. 解题 1. 题目 来源:https://tianchi.aliyun.com/oj/15165469968503404/76745683739284070 2. 解题 按道 ...

  3. 大数取模运算,快速幂取模运算

    1.快速幂取模 http://www.cnblogs.com/yinger/archive/2011/06/08/2075043.html 快速幂取模就是在O(logn)内求出a^n mod b的值. ...

  4. c语言中欧几里得模乘法逆元,扩展欧几里得算法同余方程模m乘法逆元详解

    欧几里德算法: 复习:求最大公约数算法(欧几里得算法.也叫辗转相除法).欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数. 基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd ...

  5. 2164 Bincomial Coeffcients(组合数求模)

    2164 Bincomial Coeffcients(组合数求模) Problem Description Input Output Sample Input 3 1 1 10 2 954 723 S ...

  6. 辗转相除法求模的逆元

    最近研究RSA算法,发现在这个算法里,实现过程中的核心就是求出密钥D,求密钥的公式: E*D ≡ 1 mod r ,现在已知了E和r,求E即是一个求模的逆元问题. 注:≡是数论中表示同余的符号.公式中 ...

  7. 蓝桥杯 算法提高 递推求值(矩阵快速幂)详解

    传送门 问题描述 已知递推公式: F(n, 1)=F(n-1, 2) + 2F(n-3, 1) + 5, F(n, 2)=F(n-1, 1) + 3F(n-3, 1) + 2F(n-3, 2) + 3 ...

  8. NYOJ 301 递推求值(矩阵快速幂)

    递推求值 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给你一个递推公式: f(x)=a*f(x-2)+b*f(x-1)+c 并给你f(1),f(2)的值,请求出f(n ...

  9. 矩阵的乘法和快速幂的一些理解(适用初学者)

    矩阵是线性代数的知识...后悔没好好学了... 第一部分:矩阵的基础知识 1.结合性 (AB)C=A(BC). 2.对加法的分配性 (A+B)C=AC+BC,C(A+B)=CA+CB . 3.对数乘的 ...

最新文章

  1. 你奋斗这么辛苦,这辈子要证明什么?
  2. Dependency injection in ASP.NET Core
  3. php函数dirname范例,PHP dirname( )用法及代碼示例
  4. Nginx 通过 Lua + Redis 实现动态封禁 IP
  5. java线程中的常用方法_[多线程] 线程中的常用方法-最详细
  6. 《DBNotes:Join算法的前世今生》
  7. 如何生成漫画风图片无需下载APP无需PS无需电脑
  8. T-SQL: Adding More to Our Queries
  9. 2349 Arctic Network prim最小生成树 基础
  10. Atitit图像识别的常用特征大总结attilax大总结
  11. 网吧破解还原卡的方法总结!!
  12. Linux 系统中的用户管理
  13. BrowserslistError: Unknown version 67 of android
  14. iOS运行时Runtime浅析
  15. Android源码编译(Ubuntu 14.04)
  16. 情人节相关的公众号图文这样排版,看过的都说美!
  17. How a Kalman filter works, in picture(reproduced)
  18. Android代码混淆工具Proguard学习
  19. 网站制作流程及界面交互设计研究探讨
  20. tomcat启动报javax.naming.NamingException: No naming context bound to this class loader

热门文章

  1. Windows下MySQL压缩包.zip的安装
  2. 友盟小米收不到推送消息_Android 推送集成华为,小米,友盟
  3. 根可达算法的根_好屌好屌的「GC系列」JVM垃圾定位及垃圾回收算法浅析
  4. Ajax用证书调用,跨域的jQuery AJAX调用,带证书(Cross domain jQuery ajax call
  5. java在控制台打印余弦曲线,java打印正弦曲线示例
  6. ddr3服务器内存条维修,详解服务器中内存故障的优质解决方案
  7. python 捕获鼠标点击事件,在Python中的wx.Frame外部捕获鼠标事件
  8. 西工大计算机学院交流,2017西工大计算机交流+精贵资料
  9. python数据库自动重连_python mysql断开重连的实现方法
  10. Java2精要_java知识精要(一)