BZOJ 4802: 欧拉函数(大数因数分解算法 Pollard_rho 和素数测试算法 Miller_Rabin)
Description
已知N,求phi(N)
Input
正整数N。N<=10^18
Output
输出phi(N)
Sample Input
8
Sample Output
4
Solution
我们知道 φ(n)=n(1−1p1)(1−1p2)⋅⋅⋅(1−1pk)φ(n)=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})···(1-\frac{1}{p_k})φ(n)=n(1−p11)(1−p21)⋅⋅⋅(1−pk1)
其中 n=∏pikin=\prod{p_i^{k_i}}n=∏piki ,pip_ipi 为互不相同的质数。
很自然,我们需要将 nnn 分解质因数,但是 n≤1018n\le10^{18}n≤1018 ,很大。
于是我们可以使用 Pollard_rho 算法。
其主要思想是找到两个数 p,qp,qp,q ,使得 n=p∗qn=p*qn=p∗q ,在不断继续分解。
设递归过程 proc(x)proc(x)proc(x) ,若 xxx 是质数(用 Miller_Rabin 算法判断),则 xxx 是 nnn 的一个质因数,并退出过程。
否则找到一个数 yyy ,使 gcd(x,y)>1gcd(x,y)>1gcd(x,y)>1 ,继续递归 proc(y)proc(y)proc(y) 、proc(xy)proc(\frac{x}{y})proc(yx) 。
那么怎样找到这个数呢?
我们用到了随机化的思想和生日悖论,即找到两个数 x1,x2x1,x2x1,x2 使得 gcd(∣x1−x2∣,x)>1gcd(|x1-x2|,x)>1gcd(∣x1−x2∣,x)>1 ,这样概率就会大得多。
设变换函数 f(x)=(x2+c)%mf(x)=(x^2+c)\%mf(x)=(x2+c)%m ,其中 ccc 是一个随机变量,那么令 x1,x2x1,x2x1,x2 沿着该函数一直走。
可这样走是会成环走回原点的,如下图:
它的形状形似希腊字母 ρρρ ,该算法名即得于此。
判环的话可以用 Floyd 判圈算法:x1=f(x1)x1=f(x1)x1=f(x1)x2=f(f(x2))x2=f(f(x2))x2=f(f(x2))
即 x2x2x2 以两倍速度跑,当 x1=x2x1=x2x1=x2 时重构即可。
可证单 Pollard_rho 算法的期望时间复杂度为 O(n14)O(n^{\frac{1}{4}})O(n41) 。
然而其中还有一个算法 Miller_Rabin (素数测试算法)还没介绍。
我们当然可以 O(n)O(n)O(n) 线筛出素数,但是在这种时间空间都不允许的情况下,如何快速判定单个素数呢?
根据费马小定理,当 nnn 为素数时,有: an−1≡1(modn)a^{n-1}\equiv1(mod\ n)an−1≡1(mod n)
但是当正整数 nnn 满足 an−1≡1(modn)a^{n-1}\equiv1(mod\ n)an−1≡1(mod n) 时不一定 nnn 就是素数(即逆定理不成立)。
但是我们想如果对于很多个 aaa 都满足上式,是否就能说明 nnn 就是素数了呢?
我们发现这样错误率依然很高,这时二次探测定理就派上用场了。
若一个数 xxx 满足: x2≡1(modp)x^2\equiv1(mod\ p)x2≡1(mod p) ,则合法的解就只有 x=1x=1x=1 或 x=p−1x=p-1x=p−1 。
证明很简单,就是因为 x2−1=(x+1)(x−1)x^2-1=(x+1)(x-1)x2−1=(x+1)(x−1) ,合法解显然。
那么 an−1a^{n-1}an−1 就可以拆成 ad∗2ta^{d*2^t}ad∗2t ,其中 ddd 是奇数。
那么我们先用 ada^dad 检测,之后每次平方,若 (ax)2≡1{(a^x)}^2\equiv1(ax)2≡1 则 ax≡1或p−1(modp)a^x\equiv1或p-1(mod\ p)ax≡1或p−1(mod p) 。
如此一来,检测的成功率就大了不少,更容易检测出是否为质数了。
我们只需随机几个 aaa (或拿几个质数)来判断即可,复杂度约为 log23(n)log_2^3(n)log23(n)。
至此,我们就成功地实现了算法 Miller_Rabin 和 Pollard_rho 。
Code
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
typedef long long LL;
typedef long double LD;
const int N=65,P=5,prime[P]={2,3,7,61,24251};
LL n,pn;
LL f[N];
inline LL mul(LL a,LL b,LL p)
{a%=p,b%=p;LL c=(LD)a*b/p;c=a*b-c*p;if(c<0) c+=p; elseif(c>p) c-=p;return c;
}
inline LL ksm(LL x,LL y,LL p)
{LL s=1;while(y){if(y&1) s=mul(s,x,p);x=mul(x,x,p);y>>=1;}return s;
}
inline LL twice(LL a,LL p)
{LL d=p-1;int t=0;while(!(d&1)) d>>=1,t++;//p-1=d*2^tLL x,y;x=y=ksm(a,d,p);while(t--){y=mul(x,x,p);if(y==1 && x^1 && x^p-1) return 0;x=y;}return y;
}
inline LL random(LL up)
{return (LL)rand()*rand()%up;
}
LL gcd(LL x,LL y)
{return !y?x:gcd(y,x%y);
}
inline LL abs(LL x,LL y)
{return x<y?y-x:x-y;
}
inline bool Miller_Rabin(LL x)
{for(int i=0;i<P;i++){if(x==prime[i]) return true;if(twice(prime[i],x)^1) return false;}return true;
}
inline LL trans(LL x,LL y,LL z)
{return (mul(x,x,z)+y)%z;
}
void Pollard_rho(LL m)
{if(Miller_Rabin(m)){f[++f[0]]=m;return;}LL x1=0,x2=0,c=0,p=1;while(p==1 || p==m){x1=trans(x1,c,m);x2=trans(trans(x2,c,m),c,m);while(x1==x2){c=random(m);x1=x2=random(m);x2=trans(x2,c,m);}p=gcd(abs(x1-x2),m);}Pollard_rho(p);Pollard_rho(m/p);
}
inline LL getphi(LL m)
{sort(f+1,f+1+f[0]);f[0]=unique(f+1,f+1+f[0])-(f+1);LL sum=m;for(int i=1;i<=f[0];i++)sum=sum/f[i]*(f[i]-1);return sum;
}
int main()
{scanf("%lld",&n);if(n==1) return 0&puts("1");srand(time(NULL));Pollard_rho(n);pn=getphi(n);printf("%lld",pn);return 0;
}
BZOJ 4802: 欧拉函数(大数因数分解算法 Pollard_rho 和素数测试算法 Miller_Rabin)相关推荐
- BZOJ - 2186 欧拉函数
题目的意思大概是求1~N!中和M!互质的数的个数 因为对欧拉函数理解不够深刻所以我是分析得到结果的: 当N<=M的时候显然符合要求的数的个数为0: 当N>M的时候我们要求的是1~N!中不含 ...
- bzoj 2818 欧拉函数
思路:就是对于某个数q,跟他互质的数p,kp和kq的最大公约数是k,那么这个数能组成的答案的数量就是phi[i]乘以某个质数,且乘积小于n 基于这种思路写下这个代码 #include <cstd ...
- bzoj 4805: 欧拉函数求和
Time Limit: 15 Sec Memory Limit: 256 MB Submit: 539 Solved: 304 [Submit][Status][Discuss] Descript ...
- 欧拉函数(Euler_Function)
一.基本概述 在数论,对正整数n,欧拉函数varphi(n)是少于或等于n的数中与n互质的数的数目.此函数以其首名研究者欧拉命名,它又称为Euler's totient function.φ函数.欧拉 ...
- LightOJ 1370 Bi-shoe and Phi-shoe(欧拉函数)
题意:题目给出一个欧拉函数值F(X),让我们求>=这个函数值的最小数N,使得F(N) >= F(X); 分析:这个题目有两种做法.第一种,暴力打出欧拉函数表,然后将它调整成有序的,再建立一 ...
- poj1284:欧拉函数+原根
何为原根?由费马小定理可知 如果a于p互质 则有a^(p-1)≡1(mod p)对于任意的a是不是一定要到p-1次幂才会出现上述情况呢?显然不是,当第一次出现a^k≡1(mod p)时, 记为ep(a ...
- NOI数学之提高级:欧拉定理和欧拉函数
欧拉定理详解 欧拉定理详解_郝伟老师的博客--大数据.并行计算与人工智能时代-CSDN博客_欧拉定理 欧拉函数与欧拉定理 欧拉函数与欧拉定理_leader_one的博客-CSDN博客_欧拉定理 欧拉定 ...
- UVA 11426 GCD - Extreme (II) (欧拉函数)
题目传送门:点击打开链接 假设a.b(a<b)互质,那么gcd(a,b)=1,这样当i循环到a.j循环到b时就会向结果中+1,而i循环到2*a.j循环到2*b时就会向结果中+2(gcd(2*a, ...
- bzoj 2705: [SDOI2012]Longge的问题(欧拉函数)
2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec Memory Limit: 128 MB Submit: 3077 Solved: 1914 [Submit ...
最新文章
- 新东家要哭了,雅虎终于承认上亿用户数据被盗
- GoJS超详细入门(插件使用无非:引包、初始化、配参数(json)、引数据(json)四步)...
- 转-Multicast server and client in Python
- CentOS7中编译安装redis5.0
- RSA的JavaScript程序
- 地图不显示_图灵搜不显示地图,软件打开一片空白,怎么解决?
- 深度学习TF—8.经典CNN模型—LeNet-5、VGG13、AlexNet、GoogLeNet、ResNet、DenseNet
- 计算机网络技术提纲,计算机网络技术复习提纲
- 数学建模优化模型简单例题_数学建模案例分析--最优化方法建模7习题六 -
- Vue 使用 fraola——vue-froala-wysiwyg
- linux下查看计划任务,linux查看计划任务.docx
- python网络爬虫笔记
- 面对这些可能出现的意外,你的运维团队准备好了吗?
- 怎么获取淘宝商品详情
- 第P9周:YOLOv5-Backbone模块实现
- 硬件工程师--医疗器械
- 将自己的 ubuntu 系统制作为ISO镜像
- 华为OD机试 - 字符串分割
- kaggle树叶分类
- 企业数据治理,并不止于数据