啊居然要特判,卡了好久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大整数分解算法的更多相关文章

  1. BZOJ4802:欧拉函数(Pollard-Rho,欧拉函数)

    Description 已知N,求phi(N) Input 正整数N.N<=10^18 Output 输出phi(N) Sample Input 8 Sample Output 4 Soluti ...

  2. bzoj4802 欧拉函数(附Millar-Rabin和Pollard-Rho讲解)

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4802 [题解] 参考:http://www.matrix67.com/blog/archiv ...

  3. BZOJ4802 欧拉函数 (Pollard-Rho Miller-Robin)

    题目 求大数的欧拉函数φ\varphiφ 题解 Pollard-Rho 板子 CODE #pragma GCC optimize (3) #include <bits/stdc++.h> ...

  4. 2018.12.17 bzoj4802: 欧拉函数(Pollard-rho)

    传送门 Pollard−rhoPollard-rhoPollard−rho模板题. 题意简述:求ϕ(n),n≤1e18\phi(n),n\le 1e18ϕ(n),n≤1e18 先把nnn用Pollar ...

  5. BZOJ4802 欧拉函数 数论

    原文链接http://www.cnblogs.com/zhouzhendong/p/8117744.html 题目传送门 - BZOJ4802 题意概括 Description 已知N,求phi(N) ...

  6. [BZOJ4802]欧拉函数

    bzoj description 给出\(n\),求\(\varphi(n)\).\(n\le10^{18}\) sol \(Pollard\ Rho\),存个代码. code #include< ...

  7. BZOJ 4802: 欧拉函数 (Pollard-Rho)

    开始一直T,原来是没有srand- CODE #include<bits/stdc++.h> using namespace std; typedef long long LL; vect ...

  8. 数论的欧拉定理证明 &amp; 欧拉函数公式(转载)

    欧拉函数 :欧拉函数是数论中很重要的一个函数,欧拉函数是指:对于一个正整数 n ,小于 n 且和 n 互质的正整数(包括 1)的个数,记作 φ(n) . 完全余数集合:定义小于 n 且和 n 互质的数 ...

  9. 【BZOJ4802】欧拉函数(Pollard_rho)

    [BZOJ4802]欧拉函数(Pollard_rho) 题面 BZOJ 题解 这么大的范围肯定不好杜教筛. 考虑欧拉函数的计算式,显然只需要把\(n\)分解就好了. 直接\(Pollard\_rho\ ...

随机推荐

  1. 使用 Docker 部署 Spring Boot 项目,带劲!!

    上一篇:年轻人的第一个 Docker 应用 Docker 一次构建.处处运行及快速启停的特性,在微服务架构中有着举足轻重的地位,具体的概念性的东西就不介绍了,不懂的点击这里阅读 Docker 基础教程 ...

  2. 什么是NTFS文件格式

    说到磁盘格式,想必大家对于NTFS格式并不陌生.我们使用的u盘等硬盘设备很多都应用了此格式.NTFS文件格式究竟是什么?它都有哪些特点?今天,小编将利用这篇文章为大家进行介绍. 一.什么是NTFS文件 ...

  3. 面试题59 - II. 队列的最大值

    请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value.push_back 和 pop_front 的时间复杂度都是O(1). 若队列为空,pop_front 和 ...

  4. 使用logisim搭建单周期CPU与添加指令

    使用logisim搭建单周期CPU与添加指令 搭建 总设计 借用高老板的图,我们只需要分别做出PC.NPC.IM.RF.EXT.ALU.DM.Controller模块即可,再按图连线,最后进行控制信号 ...

  5. 洛谷 P1284 三角形牧场 题解(背包+海伦公式)

    题目链接 题目大意 给你 n块木板(n<=40),每块木板长度为\(l[i]<=40\) 每块木板都要用,求最大的三角形面积×100,答案直接舍去小数 题目思路 首先如果已知三条边的长度可 ...

  6. 牛客练习赛71 数学考试 题解(dp)

    题目链接 题目大意 要你求出有多少个长度为n的排列满足m个限制条件 第i个限制条件 p[i]表示前 p[i]个数不能是1-p[i]的排列 题目思路 这个感觉是dp但是不知道怎么dp 首先就是要明白如果 ...

  7. 通过Consul Raft库打造自己的分布式系统

    通用的CP系统有etcd和consul, 通用的对立面就是专用系统. 所以在某些场合是有这种需求的. 然而etcd embed的可用性极差, Windows上面跑会出现各种问题, 而且不能定制协议, ...

  8. C++基础入门知识:C++命名空间(名字空间)详解

    一个中大型软件往往由多名程序员共同开发,会使用大量的变量和函数,不可避免地会出现变量或函数的命名冲突.当所有人的代码都测试通过,没有问题时,将它们结合到一起就有可能会出现命名冲突. 例如小李和小韩都参 ...

  9. [BUGCASE]FixedDataTable表格数据渲染错误

    一.问题描述 广告配置中绑定第三方规格ID表格数据,有一部分展示错乱,具体如下: 表格组件使用 Facebook 的 (fixed-data-table) 组件 二.原因分析 1.检查props 先查 ...

  10. 冲刺随笔——Day_Two

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 团队进行Alpha冲刺 作业正文 正文 其他参考文献 无 ...