bzoj-2186 (欧拉函数+费马小定理求逆元)
来源:互联网 发布:软件项目外包网站 编辑:程序博客网 时间:2024/06/05 10:18
Description
大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票。房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量。现在,请你帮助沙拉公主解决这个问题,由于可能张数非常大,你只需计算出对R取模后的答案即可。R是一个质数。
Input
第一行为两个整数T,R。R<=10^9+10,T<=10000,表示该组中测试数据数目,R为模后面T行,每行一对整数N,M,见题目描述 m<=n
Output
共T行,对于每一对N,M,输出1至N!中与M!素质的数的数量对R取模后的值
Sample Input
1 114 2Sample Output
1数据范围:对于100%的数据,1 < = N , M < = 10000000
题目题意:题目给我们n,m让我们求出在1到n!之内与m!互质的个数%r
题目分析:想到互质的对的对数,我们很容易想到的是欧拉函数,即在1到m!之内与m!互质对数可以用欧拉函数很快求出,但是m!+1到n!与m!互质的对数怎么求了?
我一开始的想法是容斥。。。。。。很明显,数据太大了,不可能的。
下面我们来注意一个式子:
gcd(a+b,b)=gcd(b,(a+b)%b)=gcd(b,a%b)=gcd(a,b)
也就是说a与b互质,那么a+b与b也互质,
我们刚刚说了的在1到m!与m!互质的可以用欧拉函数快速求出,我们就利用刚刚结论:
a+k*m!<=n! (a与m!互质,那么a+k*m!也一定与m!互质)
即k<=n!/m!-a/n!
则在n!内(数字a和他们兄弟a+k*m!)与m!互质,且个数为n!/m!,
数字a是属于1到m!的,这个a的个数就是phi[m!]
我们得到了答案为:
phi[m!]*(n!/m!)%r
我们把式子展开:(欧拉函数用原始式子表示)
m!*(1-1/p1)*(1-1/p2)*.......(1-1/pn)*(n!/m!)%r(p1,p2,,,pn为m!的质因子)
化简得(1-1/p1)*(1-1/p2)*......*(1-1/pn)*n!%r
现在我们的问题变成了求m!的质因子:
我们由勒让德定理知道
在正数n!的素因子标准分解式中,素数p的指数记作 ,则 .
不难发现任何小于m的质因子都是m!的质因子(因为n/p肯定不为0)
我们接着变形:
(p1-1)/p1*(p2-1)/p2*.......*n!%r;
里面有除法,和明显得用逆元,我们有费马小定理:
假如p是质数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p)
我们把式子变一下:a*a^(p-2)=1 mod p
即a^(p-2)=1/a mod p
即a^(p-2)就是逆元。
代码如下:
#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#define ll long longusing namespace std;const int maxn=1e7+10;int prime[maxn],cnt;bool vis[maxn];void get_prime()//打素数表{ memset (vis,true,sizeof (vis)); vis[1]=false; for (int i=2;i<maxn;i++) { if (vis[i]) prime[cnt++]=i; for (int j=0;j<cnt&&i*prime[j]<maxn;j++) { vis[i*prime[j]]=false; if (i%prime[j]==0) break; } }}ll fast_pow(ll base,ll k,ll mod)//快速幂,,求逆元{ ll ans=1; while (k) { if (k&1) ans=ans*base%mod; base=base*base%mod; k>>=1; } return ans;}const int inf=1e7+10;ll fac[inf],ans[inf];void init(ll mod)//打表{ fac[0]=fac[1]=1; for (int i=2;i<inf;i++)//求N! fac[i]=fac[i-1]*i%mod; ans[1]=1; for (int i=2;i<inf;i++) { if (!vis[i]) ans[i]=ans[i-1];//i不是素数的话,就不变 else ans[i]=(ans[i-1]*(i-1)%mod*fast_pow(i,mod-2,mod))%mod;//逆元 }}int main(){ get_prime(); ll t,r,n,m; scanf("%lld%lld",&t,&r); init(r); while (t--) { scanf("%lld%lld",&n,&m); printf("%lld\n",fac[n]*ans[m]%r); } return 0;}
阅读全文
0 0
- bzoj-2186 (欧拉函数+费马小定理求逆元)
- BZOJ-1951-古代猪文-SDOI2010-费马小定理+欧拉函数+lucas定理+中国剩余定理
- 欧拉函数、欧拉定理、费马小定理
- 原根,欧拉函数,欧拉定理,费马小定理
- 欧拉函数-欧拉定理-费马小定理
- BZOJ 3884 [欧拉定理]
- 费马小定理和排列组合 欧拉函数
- 费马小定理&&欧拉定理
- BZOJ 1409 快速幂+欧拉定理
- 威尔逊定理,费马小定理,欧拉定理
- 欧拉函数及定理
- 欧拉定理与函数
- 欧拉函数与欧拉定理
- 欧拉函数与欧拉定理
- 欧拉函数&&欧拉定理
- 欧拉定理,欧拉函数
- 欧拉函数与欧拉定理
- 欧拉函数/欧拉定理
- 轻松学JVM——基本原理
- 学生信息系统学习心得三、学生1.5系统用户管理模块的创建
- HDU 4675-GCD of Sequence(莫比乌斯反演+组合数+逆元)
- 校园招聘[源码+项目展示]
- 类型基础
- bzoj-2186 (欧拉函数+费马小定理求逆元)
- Javascript所有数组方法详解
- CSS实现表格项斜角
- JRebel无限制版
- HP-Socket v5.0.1:支持 IPv6 及多 SSL 证书
- 名校不是门槛,吴恩达:培养一百万个AI人才 | 数据周报
- 虚拟币开发专题(山寨币怎样用Qt命令行分析区块信息)
- java.io.FileNotFoundException: .\xxx\xxx.png (系统找不到指定的路径。)
- 大公司里怎样开发和部署前端代码?