bzoj4802 欧拉函数(附Millar-Rabin和Pollard-Rho讲解)
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4802
【题解】
参考:http://www.matrix67.com/blog/archives/234
Millar-Rabin质数检验方法:
根据费马小定理,如果p是素数,a<p,那么有a^(p-1) mod p = 1。
直观想法我们直接取若干个a,如果都有一个不满足,那么p就是合数。
遗憾的是,存在Carmichael数:你无论取多少个a,有一个不满足,算我输。
比如:561 = 11*51就是一个Carmichael数。

那么就很江了啊。。我们需要改进算法。
首先有:如果p是素数,x是小于p的正整数,且x^2 mod p = 1,那么要么x=1,要么x=p-1
(这个废话,x=p-1模意义下等于x=-1)
然后我们可以展示下341满足2^340 mod 341 = 1,却不是素数(341=31*11)的原因:
2^340 mod 341 = 1
2^170 mod 341 = 1
2^85 mod 341 = 32
(32这个数很py啊怎么不等于340也不等于1啊。。这明显有交易嘛)
那么就能说明这个数不是素数。
如果是素数,一定是从p-1变到1,或是把所有2的次幂去除完,本来就等于1(这样平方完就一直是1了)
所以要么把所有2的次幂去除完,本来就等于1,要么存在某一个次幂=p-1(这样就正常多了)
这就是Millar-Rabin素数验证的二次探测。
应该来说Millar-Rabin算法也是挺好写的
其中mul(a,b,c)表示a*b%c(因为a*b会爆longlong,所以用快速加)
namespace Millar_Rabin {
const int Prime[] = {, , , , , , , , , , , , , };
const int PN = ;
inline bool witness(int pr, ll res, int times, ll n) {
ll p = pwr2((ll)pr, res, n);
if(p == ) return ;
for (int i=; i<times; ++i) {
if(p == n-) return false;
if(p == ) return false;
p = mul(p, p, n);
}
return true;
}
inline bool main(ll n) {
for (int i=; i<=PN; ++i) {
if(n == Prime[i]) return ;
if(n % Prime[i] == ) return ;
}
ll p = n-;
int times = ;
while(!(p&)) {
++times;
p >>= ;
}
for (int i=; i<=PN; ++i)
if(witness(Prime[i], p, times, n)) return false;
return true;
}
}
然后我们会检验素数了,现在要质因数分解。
好了下一个是Pollard-Rho算法:
如果现在拆分的是n:Pollard-Rho(n)
主要流程:Millar-Rabin判断是否质数,是返回,否就试图找出其中一个因子d,然后递归做Pollard-Rho(d)和Pollard-Rho(n/d)。
我猜你会说废话这谁都会。问题在于:试图找出其中一个因子d
参考:https://wenku.baidu.com/view/3db5c7a6ad51f01dc381f156.html?from=search
参考文章讲的非常详细了。。我就不细讲了qwq
所以这题就是分解因数,按照欧拉函数定义式求解即可。
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h> using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + ;
const int mod = 1e9+; # define RG register
# define ST static inline ll mul(ll a, ll b, ll mod) {
ll ret = ;
a %= mod, b %= mod;
while(b) {
if(b&) {
ret = ret + a;
if(ret >= mod) ret -= mod;
}
a <<= ;
if(a >= mod) a -= mod;
b >>= ;
}
return ret;
} inline ll pwr2(ll a, ll b, ll mod) {
ll ret = ;
a %= mod;
while(b) {
if(b&) ret = mul(ret, a, mod);
a = mul(a, a, mod);
b >>= ;
}
return ret;
} inline ll gcd(ll a, ll b) {
return b== ? a : gcd(b, a%b);
} namespace Millar_Rabin {
const int Prime[] = {, , , , , , , , , , , , , };
const int PN = ; inline bool witness(int pr, ll res, int times, ll n) {
ll p = pwr2((ll)pr, res, n);
if(p == ) return ;
for (int i=; i<times; ++i) {
if(p == n-) return false;
if(p == ) return false;
p = mul(p, p, n);
}
return true;
} inline bool main(ll n) {
for (int i=; i<=PN; ++i) {
if(n == Prime[i]) return ;
if(n % Prime[i] == ) return ;
}
ll p = n-;
int times = ;
while(!(p&)) {
++times;
p >>= ;
}
for (int i=; i<=PN; ++i)
if(witness(Prime[i], p, times, n)) return false;
return true;
}
} namespace PollardRho {
const int N = ;
ll q[N]; int qn; inline void PR(ll n) {
if(Millar_Rabin::main(n)) {
q[++qn] = n;
return ;
}
ll a, b, c, del;
while() {
c = rand() % n;
a = b = rand() % n;
b = (mul(b, b, n) + c) % n;
while(a != b) {
del = a-b;
del = gcd(abs(del), n);
if(del > && del < n) {
PR(del); PR(n/del);
return ;
}
a = (mul(a, a, n) + c) % n;
b = (mul(b, b, n) + c) % n;
b = (mul(b, b, n) + c) % n;
}
}
} inline ll getphi(ll n) {
if(n == ) return 1ll;
sort(q+, q+qn+);
ll res = q[] - ;
for (int i=; i<=qn; ++i) {
if(q[i] != q[i-]) res = res * (q[i] - );
else res = res * q[i];
}
return res;
} inline void main(ll n) {
qn = ;
PR(n);
cout << getphi(n) << endl;
}
} int main() {
srand();
ll n; cin >> n;
if(n == ) {
puts("");
return ;
}
PollardRho::main(n);
return ;
}
bzoj4802 欧拉函数(附Millar-Rabin和Pollard-Rho讲解)的更多相关文章
- BZOJ4802:欧拉函数(Pollard-Rho,欧拉函数)
Description 已知N,求phi(N) Input 正整数N.N<=10^18 Output 输出phi(N) Sample Input 8 Sample Output 4 Soluti ...
- BZOJ4802 欧拉函数 (Pollard-Rho Miller-Robin)
题目 求大数的欧拉函数φ\varphiφ 题解 Pollard-Rho 板子 CODE #pragma GCC optimize (3) #include <bits/stdc++.h> ...
- [日常摸鱼]bzoj4802 欧拉函数-PollardRho大整数分解算法
啊居然要特判,卡了好久QAQ (好像Windows下的rand和Linux下的不一样? QwQ一些东西参考了喵铃的这篇blog:http://www.cnblogs.com/meowww/p/6400 ...
- BZOJ4802 欧拉函数 数论
原文链接http://www.cnblogs.com/zhouzhendong/p/8117744.html 题目传送门 - BZOJ4802 题意概括 Description 已知N,求phi(N) ...
- 2018.12.17 bzoj4802: 欧拉函数(Pollard-rho)
传送门 Pollard−rhoPollard-rhoPollard−rho模板题. 题意简述:求ϕ(n),n≤1e18\phi(n),n\le 1e18ϕ(n),n≤1e18 先把nnn用Pollar ...
- [BZOJ4802]欧拉函数
bzoj description 给出\(n\),求\(\varphi(n)\).\(n\le10^{18}\) sol \(Pollard\ Rho\),存个代码. code #include< ...
- 【BZOJ4802】欧拉函数(Pollard_rho)
[BZOJ4802]欧拉函数(Pollard_rho) 题面 BZOJ 题解 这么大的范围肯定不好杜教筛. 考虑欧拉函数的计算式,显然只需要把\(n\)分解就好了. 直接\(Pollard\_rho\ ...
- 数学基础IV 欧拉函数 Miller Rabin Pollard's rho 欧拉定理 行列式
找了一些曾经没提到的算法.这应该是数学基础系最后一篇. 曾经的文章: 数学基础I 莫比乌斯反演I 莫比乌斯反演II 数学基础II 生成函数 数学基础III 博弈论 容斥原理(hidden) 线性基(h ...
- BZOJ2186 欧拉函数
欧拉函数:一般记作φ(n),表示1-n中与n互质的数的数量. 欧拉函数是积性函数,即φ(m*n)=φ(m)*φ(n) //这条定理基友面试时还遇到了= = 欧拉函数的值φ(n)=n*(1-p[1])* ...
随机推荐
- WMS与MES集成
ERP的物流管理只偏重于帐务的管理,对现场实物流的及时性和精细程度管理均不够,无法满足企业日益精细化管理的需求,WMS可以弥补这个缺陷,WMS采用条码技术及时反应物流过程中的变化,同时将存量细化到货架 ...
- hdu 5126 stars (四维偏序,离线,CDQ套CDQ套树状数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5126 思路:支持离线,那么我们可以用两次CDQ分治使四维降为二维,降成二维后排个序用树状数组维护下就好 ...
- Fail2ban 配置
本例为wordpress管理员登陆限制安装rpm -Uvh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.n ...
- 值得Python小白学习的书 简单推荐几本吧
于我个人而言,我很喜欢Python,当然我也有很多的理由推荐你去学python.我只说两点.一是简单,二是写python薪资高.我觉得这俩理由就够了,对不对.买本书,装上pycharm,把书上面的例子 ...
- Elasticsearch利用cat api快速查看集群状态、内存、磁盘使用情况
使用场景 当Elasticsearch集群中有节点挂掉,我们可以去查看集群的日志信息查找错误,不过在查找错误日志之前,我们可以通过elasticsearch的cat api简单判断下各个节点的状态,包 ...
- exec函数族的使用
作者:王姗姗,华清远见嵌入式学院讲师. exec用被执行的程序完全替换调用它的程序的影像.fork创建一个新的进程就产生了一个新的PID,exec启动一个新程序,替换原有的进程,因此这个新的被exec ...
- Hadoop、Hbase基本命令及调优方式
HDFS基本命令 接触大数据挺长时间了,项目刚刚上完线,趁着空闲时间整理下大数据hadoop.Hbase等常用命令以及各自的优化方式,当做是一个学习笔记吧. HDFS命令基本格式:Hadoop fs ...
- CrossFire Round #481 div.3 978 打后感
虚拟赛,头一次打div.3感觉好TM水啊...... 一共7道题,我A了6道,第7题有思路但是没时间了. 结果还是排在700多名,可能其他人也觉得太水了吧. 逐一解析题目: A好简单,因为不想离散化我 ...
- “由于下列错误,Parallel port driver 服务启动失败”,注意了
最近在“事件查看器”中发现这么一个错误:“由于下列错误,Parallel port driver 服务启动失败”, 我到网上搜索了一下,发现很多网页上都说解决办法: 把HKEY_LOCAL_MACHI ...
- 跟我一起学习vue2(使用命令行搭建单页应用)[二]
第一步:运行git命令,全局安装 vue-cli $ cnpm install --global vue-cli 第二步: 创建一个基于 webpack 模板的新项目 $ vue init webpa ...