[日常摸鱼]bzoj4802 欧拉函数-PollardRho大整数分解算法
啊居然要特判,卡了好久QAQ
(好像Windows下的rand和Linux下的不一样?
QwQ一些东西参考了喵铃的这篇blog:http://www.cnblogs.com/meowww/p/6400841.html (业界良心)
题意:输入$n$,求$phi(n)$,$n \leq 10^{18}$
随便抽的题,刚好学习一下相关的算法。
很明显朴素的根号算法时间复杂度补滋兹,线性筛更不用想了,不过这题只需要单个欧拉函数值,还是直接考虑$phi(n)=n*\prod_{i=1}^k(1-\frac{1}{p_i})$这种求法吧,根号算法的瓶颈在于没办法快速确定有哪些约数,如果我们能快速的对$n$进行质因数分解就好了。
前置技能(pre-skill)
费马小定理
- 若对素数模数$p$有$a^p \equiv a \pmod p$,证明挺多的所以我就略了(上面那篇blog也有)
Miller-Rabin素性测试
- 对于朴素的判定素数的方法复杂度也是根号的,尽管这种复杂度其实已经挺快的了,但是有时候还需要更高效率的素性测试,注意到上面的费马小定理,如果在$[1,p-1]$内随机选十几个$a$来代到上面的式子里去,也许可以?
- 我实际测试了一下确实基本上能够很准确的判断素性(好吧其实我写了个对拍居然一直没拍出问题来 [真是叫人质壁分离.jpg]),在随机数据下正确率还是挺高的,之前也见过有人在比赛的时候这么判素数…
- 但是!有个叫卡米歇尔的人发现了这样一些数,他们是合数但是不论$a$怎么取都能通过上面这种测试,最小的一个是561=3*11*17,像这样的数还有许多,他们被称作卡米歇尔数,不过这已经不是我们要讨论的重点。
- Miller-Rabin素性测试:对于某个大于1的奇数$n$,令$2^{\alpha}t=n-1$,$t$为奇数,对于$n \not | a$的某个$a$如果有$a^t \not \equiv 1 \pmod n$且$\forall 0 \leq i \leq \alpha -1,a^{2^{i}t} \not \equiv n-1 \pmod p$,则$n$一定是合数。可以证明和它等价的逆否命题,具体的上面那篇blog讲的非常清楚就不债述了QwQ
- 这就是miller-rabin素性测试了,看起来比较麻烦而且,不过这种方法的好处就在于它不存在像上面卡米歇尔数一样不论如何都无法正确判断的情况。需要注意的是实现的时候由于经常是对很大的数进行素性测试,乘法需要用类似快速幂那样的写法来实现,不然可能会溢出,具体的实现放在后面的代码里面了,就是那个check函数。
Pollard-Rho大整数分解算法(zheng ti)
好了现在终于可以回到最开始的那个问题了,我们需要快速地对一个数进行质因数分解。
我们假装找到了一个因子
- 分解之前先用上面的素性测试判断$n$是不是一个素数,如果不是的话,假装我们已经可以找到了$n$的一个因子$d$,那么就可以递归的去分解$d$和$n/d$,现在我们的问题就是要怎么快速的找到这个因子。
- 嗯还是上面的那篇blog,已经非常清楚的讲了怎么分解出这个$d$了~我不觉得我可以写得更好所以我就不写了(才不是因为懒)
好了现在回到原来的题目,用Pollard-Rho算法分解出$n$的所有因子排个序就好辣。
注意:特判1 特判1 特判1
细节都在里面啦,我写的好像比较挫在bzoj上跑了一百多ms…
T_T搞不懂那些10ms内的怎么写的
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long lint; inline lint mul(lint a,lint b,lint p)
{
lint res=0;a%=p;b%=p;
for(;b;b>>=1,a=(a<<1)%p)if(b&1)res=(res+a)%p;
return res;
}
inline lint pow_mod(lint a,lint b,lint p)
{
lint res=1;a%=p;
for(;b;b>>=1,a=mul(a,a,p))if(b&1)res=mul(res,a,p);
return res;
}
inline lint gcd(lint a,lint b)
{
return !b?a:gcd(b,a%b);
}
inline lint get(lint x)
{
return rand()%x;
//return mul(mul(rand(),rand(),x),mul(rand(),rand(),x),x);
}
inline lint range(lint a,lint b)
{
return a+get(b-a+1);
}
inline bool check(lint x)
{
lint temp[15]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
for(register int i=0;i<15;i++)
{
if(x==temp[i])return 1;
if(x%temp[i]==0)return 0;
}
lint s,a,k=0,t=x-1;
while(!(t&1))
{
t>>=1;
k++;
}
for(register lint i=1;i<=20;i++)
{
a=range(2,x-1);
s=pow_mod(a,t,x);
if(s==1)return 1;
for(register lint j=0;j<=k-1;j++)
{
s=mul(s,s,x);
if(s==x-1)return 1;
}
}
return 0;
} lint q[115],tot;
#define f(p) ((mul(p,p,x)+c)%x)
inline void solve(lint x)
{
if(check(x))
{
q[++tot]=x;return;
}
while(1)
{
lint a,b,c;
a=b=range(0,x-1);c=range(0,x-1);b=f(b);
while(a!=b)
{
lint temp=a-b;
temp=gcd(abs(temp),x);
if(1<temp&&temp<x)
{
solve(temp);solve(x/temp);
return;
}
a=f(a);b=f(f(b));
}
}
}
int main()
{
srand(19260817);
lint n,res;scanf("%lld",&n);
if(n==1)
{
printf("1");
return 0;
}
solve(n);sort(q+1,q+tot+1);
res=n;
for(register int i=1;i<=tot;i++)if(q[i]!=q[i-1])res=(res/q[i])*(q[i]-1);
printf("%lld",res);
return 0;
}
后记
到此为止算是啃完了meow那篇blog了,感觉受益匪浅。
其实暑假有学过这个算法但是当时还是不太清楚加上几个月没写基本上忘得差不多了,今天重新回来学了一遍应该算捡起来了。
在做这道题的时候顺便去查了些相关的东西,之前因为没有特判掉1所以一直挂掉加上今天下午去打了场比赛就这样基本花了一整天(虽然我中间还去打了几把game)
(听说我错别字特别多?)
[日常摸鱼]bzoj4802 欧拉函数-PollardRho大整数分解算法的更多相关文章
- BZOJ4802:欧拉函数(Pollard-Rho,欧拉函数)
Description 已知N,求phi(N) Input 正整数N.N<=10^18 Output 输出phi(N) Sample Input 8 Sample Output 4 Soluti ...
- bzoj4802 欧拉函数(附Millar-Rabin和Pollard-Rho讲解)
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4802 [题解] 参考:http://www.matrix67.com/blog/archiv ...
- BZOJ4802 欧拉函数 (Pollard-Rho Miller-Robin)
题目 求大数的欧拉函数φ\varphiφ 题解 Pollard-Rho 板子 CODE #pragma GCC optimize (3) #include <bits/stdc++.h> ...
- 2018.12.17 bzoj4802: 欧拉函数(Pollard-rho)
传送门 Pollard−rhoPollard-rhoPollard−rho模板题. 题意简述:求ϕ(n),n≤1e18\phi(n),n\le 1e18ϕ(n),n≤1e18 先把nnn用Pollar ...
- BZOJ4802 欧拉函数 数论
原文链接http://www.cnblogs.com/zhouzhendong/p/8117744.html 题目传送门 - BZOJ4802 题意概括 Description 已知N,求phi(N) ...
- [BZOJ4802]欧拉函数
bzoj description 给出\(n\),求\(\varphi(n)\).\(n\le10^{18}\) sol \(Pollard\ Rho\),存个代码. code #include< ...
- BZOJ 4802: 欧拉函数 (Pollard-Rho)
开始一直T,原来是没有srand- CODE #include<bits/stdc++.h> using namespace std; typedef long long LL; vect ...
- 数论的欧拉定理证明 & 欧拉函数公式(转载)
欧拉函数 :欧拉函数是数论中很重要的一个函数,欧拉函数是指:对于一个正整数 n ,小于 n 且和 n 互质的正整数(包括 1)的个数,记作 φ(n) . 完全余数集合:定义小于 n 且和 n 互质的数 ...
- 【BZOJ4802】欧拉函数(Pollard_rho)
[BZOJ4802]欧拉函数(Pollard_rho) 题面 BZOJ 题解 这么大的范围肯定不好杜教筛. 考虑欧拉函数的计算式,显然只需要把\(n\)分解就好了. 直接\(Pollard\_rho\ ...
随机推荐
- 博客新域名www.tecchen.tech
新年祝福 祝新的一年,大朋友实现所有梦想,小朋友健康成长- 新域名 https://www.tecchen.tech 有效期:10年 旧链接 之前的链接请自行替换为新链接地址,包括但不限于以下二级域名 ...
- 安装Ubuntu16.04系统后分辨率底的问题
问题描述:安装Ubuntu系统后有可能会遇到分辨率很低的问题,别着急,这是一个小问题. 解决方案:修改/etc/default/grub,打开终端用命令:sudo gedit /etc/default ...
- iMindMap思维导图中可以插入哪些附件?
iMindMap(Windows系统)不仅拥有灵活的排版功能,而且还允许用户插入多种附件,丰富思维导图的内容.用户可以为思维导图添加图片.网址.录音等文件,让导图更显生动性.实用性. 将图片.录音等文 ...
- Guitar Pro编辑歌词教程
吉他是常见的乐器之一,弹唱亦是音乐爱好者们最常见的表演方式.Guitar Pro(win系统)是吉他爱好者最常用的吉他谱制作软件,大家可以在该软件上创作自己的吉他谱.既然有了谱子,那自然是少不了歌词了 ...
- 数据丢失如何恢复?EasyRecovery帮你快速实现
在日常使用电脑时,我们经常会遇到误删文件的情况,若文件还未被彻底删除,我们还可以通过电脑中的回收站将其恢复,但若是回收站都被清空的话,想要恢复文件就变得比较困难了,而EasyRecovery可以很好的 ...
- 如何使用OCR编辑器检查和识别文本
ABBYY FineReader 15(Windows系统)中的OCR编辑器能帮助用户对扫描仪或者数码相机获取的图像文件进行自动文本识别,OCR区域绘制等,使这些图像文件能进一步转换为可编辑的格式.其 ...
- 追踪聚光特效怎么实现,有Vegas就够了
舞台聚光灯大家一定都不陌生,在电视上某些颁奖活动里,主持人的进场一定伴随着舞台灯光的聚光效果.随着主持人的移动,灯光也随之移动.这里的舞台灯光就起到了一个追踪聚光的效果. Vegas Pro 16 增 ...
- Improving Commonsense Question Answering by Graph-based Iterative Retrieval over Multiple Knowledge Sources —— 基于多知识库迭代检索的常识问答系统
基于多知识库迭代检索的问答系统 论文地址 背景 常识问答任务需要引入外部知识来帮助模型更好地理解自然语言问题,现有的解决方案大都采用两阶段框架: 第一阶段 -- 从广泛的知识来源中找到与给定问题相关的 ...
- centos克隆虚拟机
首先我们把所要克隆的虚拟机关机,然后在所要克隆的虚拟机上右键,选择管理,选择克隆,出现如下界面: 点击下一步,选择虚拟机的当前状态,继续点击下一步 接着选择创建完整克隆,选择这个时,表明克隆出来的这个 ...
- Yali 2019-8-15 test solution
T1. 送货 Description 物流公司要用m辆车派送n件货物.货物都包装成长方体,第i件的高度为hi,重量为wi.因为车很小,一辆车上的货物必须垒成一摞.又因为一些不可告人的原因,一辆车上货物 ...