HDU 5407(2015多校10)-CRB and Candies(组合数最小公倍数+乘法逆元)
2015-08-22 11:13
507 查看
题目地址:HDU 5407
题意:CRB有n颗不同的糖果,现在他要吃掉k颗(0<=k<=n),问k取0~n的方案数的最小公倍数是多少。
思路:首先做这道题我们需要必备的几个技能点。
1. LCM(C(n,0), C(n,1),…, C(n,n))=LCM(1,2,3,…n+1)/(n+1)。额,这个有一篇证明Kummer定理
2.(1) 乘法逆元定义:
满足a*k≡1 (mod p)的k值就是a关于p的乘法逆元(a,p互质)。
(2)为什么要用乘法逆元:
当我们要求(a/b) mod p的值,且a很大,无法直接求得a/b的值时,我们就要用到乘法逆元。我们可以通过求b关于p的乘法逆元k,将a乘上k再模p,即(a*k) mod p。其结果与(a/b) mod p等价。
(3)乘法逆元的解法:
A:逆元可以用扩展欧几里德来解最小的正整数即可:
a*x%p = 1;
a*x = y*p + 1;
a*x -p*y = 1;
B:当p是质数的时候 a/x mod p=a*x^(p-2) mod p
证明:若 a*b mod p = 1 则a和b互为乘法逆元。因为p是质数,所以由费马小定理得出x^(p-1) mod p = 1 ,所以x*x^(p-2) mod p = 1是成立的,所以x 和 x^(p-2) 互为乘法逆元。
当p不是质数的时候a/x mod p=a*x^(phi(p)-1) mod p。
题意:CRB有n颗不同的糖果,现在他要吃掉k颗(0<=k<=n),问k取0~n的方案数的最小公倍数是多少。
思路:首先做这道题我们需要必备的几个技能点。
1. LCM(C(n,0), C(n,1),…, C(n,n))=LCM(1,2,3,…n+1)/(n+1)。额,这个有一篇证明Kummer定理
2.(1) 乘法逆元定义:
满足a*k≡1 (mod p)的k值就是a关于p的乘法逆元(a,p互质)。
(2)为什么要用乘法逆元:
当我们要求(a/b) mod p的值,且a很大,无法直接求得a/b的值时,我们就要用到乘法逆元。我们可以通过求b关于p的乘法逆元k,将a乘上k再模p,即(a*k) mod p。其结果与(a/b) mod p等价。
(3)乘法逆元的解法:
A:逆元可以用扩展欧几里德来解最小的正整数即可:
a*x%p = 1;
a*x = y*p + 1;
a*x -p*y = 1;
B:当p是质数的时候 a/x mod p=a*x^(p-2) mod p
证明:若 a*b mod p = 1 则a和b互为乘法逆元。因为p是质数,所以由费马小定理得出x^(p-1) mod p = 1 ,所以x*x^(p-2) mod p = 1是成立的,所以x 和 x^(p-2) 互为乘法逆元。
当p不是质数的时候a/x mod p=a*x^(phi(p)-1) mod p。
#include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm> #include <set> #include <queue> #include <stack> #include <map> #include <bitset> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const double pi= acos(-1.0); const double esp=1e-7; const int Maxn=1e6+10; const int mod=1000000007; bitset<Maxn>pri; int prime[Maxn]; int vis[Maxn]; int k; LL x; LL f[Maxn]; void is_prime() { pri.set(); for(int i=2;i<Maxn;i++){ if(pri[i]){ prime[k++]=i; for(int j=i+i;j<Maxn;j+=i) pri[j]=0; } } } LL Mul(LL a,LL b,LL mod) { LL res=0; while(b>0) { if(b&1) res=(res+a)%mod; b>>=1; a=(a+a)%mod; } return res; } LL modxp(LL a,LL b,LL mod) { LL res=1; while(b>0) { if(b&1) res=Mul(res,a,mod); b>>=1; a=Mul(a,a,mod); } return res; } void get() { memset(vis,0,sizeof(vis)); for(int i=0;i<k;i++){//将素数p的k次方p^k标记一下,找出符合的素数 x=prime[i]; while(x<Maxn){ vis[x]=prime[i]; x*=prime[i]; } } f[1]=1; for(int i=2;i<Maxn;i++){ if(vis[i]) f[i]=(f[i-1]*vis[i])%mod; else f[i]=f[i-1]%mod; } } int main() { int T,n; is_prime(); get(); scanf("%d",&T); while(T--){ scanf("%d",&n); printf("%lld\n",f[n+1]*modxp(n+1,mod-2,mod)%mod);//(f(n+1)/(n+1))%mod } return 0; }
相关文章推荐
- POJ 2478 Farey Sequence
- Android source build/envsetup.sh 及lunch 过程
- POJ 1745 Divisibility (线性dp)
- 优秀项目经理应备技能06-项目组织的特性与类型
- Go各种类型转换及函数的高级用法
- Visual Basic相关图书推荐
- UI-UILabel
- LNMP(linux+nginx+mysql+php)服务器环境配置
- SPOJ 2832 DETER3 - Find The Determinant III(矩阵行列式)
- acm题为什么总是出现wrong answer。。。求大神救助
- 在Ubuntu 14.04 64bit上安装下载管理器FlareGet 4.2.92
- Struts(18)标签
- HDU 3341 状态压缩DP+AC自动机
- Web开发步骤
- LUA--string的使用
- CSS3入门之文本与字体
- 应用dom4j读取xml的例子
- 在C#代码中应用Log4Net系列教程(附源代码)【转载】
- Linux HugePage特性
- 响应式网页设计