[日常摸鱼]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\ ...
随机推荐
- TCP的ACK机制
下面是整个的tcp的三次握手和四次挥手的协议 TCP四次挥手 在客户端先发送一个FIN的包,表示要close(),客户端想和连接断开,发完之后出于FIN_WAIT_1状态下:服务端收到之后就变成CLO ...
- 下载器Folx如何实现排队下载功能
用户在下载多个文件时,当然会希望这些文件都能同时下载,以达到短时间内完成下载任务的目的.但另一方面来说,同时下载过多文件,会分散带宽资源,降低了每个文件的下载速度,从而导致下载时间的延长. 为了实现多 ...
- Improving Commonsense Question Answering by Graph-based Iterative Retrieval over Multiple Knowledge Sources —— 基于多知识库迭代检索的常识问答系统
基于多知识库迭代检索的问答系统 论文地址 背景 常识问答任务需要引入外部知识来帮助模型更好地理解自然语言问题,现有的解决方案大都采用两阶段框架: 第一阶段 -- 从广泛的知识来源中找到与给定问题相关的 ...
- linux(centos7.x)安装jdk
一.下载与安装 下载地址:链接:https://pan.baidu.com/s/1g7MF1xqlOxWnLGf2shl3NA 提取码:epae 下载完成后将安装包上传到linxu环境中,并将其 ...
- Beta冲刺——用户测试报告
这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta 冲刺 这个作业的目标 团队进行Alpha冲刺 作业正文 正文 其他参考文献 无 用户测试报告 用户 ...
- 在执行gem install redis时 : ERROR: Error installing redis: redis requires Ruby version >= 2.2.2
在执行gem install redis时 提示: gem install redis ERROR: Error installing redis: redis requires Ruby versi ...
- 第3.10节 Python强大的字符串格式化新功能:使用format字符串格式化
一. 引言 前面两节介绍的字符串格式化方法,都有其本身对应的缺陷,老猿不建议大家使用,之所以详细介绍主要是考虑历史代码的兼容性,方便大家理解前人留下的代码.老猿推荐大家新编码时使用format方 ...
- 第8.18节 Python类中内置析构方法__del__
一. 引言 基本上所有支持OOP设计的语言都支持析构方法(也称析构函数),析构方法都是在对象生命周期结束时调用,一般用来实施实例相关生命周期内访问数据的扫尾工作,包括关闭文件.释放内存.输出日志.清理 ...
- PyQt学习随笔:重写setData方法截获Model/View中视图数据项编辑的注意事项
根据<PyQt学习随笔:Model/View中视图数据项编辑变动实时获取变动数据的方法>可以重写从PyQt的Model类继承的setData方法来实时截获View中对数据的更改,但需要注意 ...
- PyQt学习随笔:Qt中Model/View中的怎么构造View匹配的Model
老猿Python博文目录 老猿Python博客地址 在<PyQt学习随笔:Qt中Model/View相关的主要类及继承关系>介绍了Model/View架构的主要类,在实际使用时,view相 ...