啊居然要特判,卡了好久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. 深度分析:面试腾讯,阿里面试官都喜欢问的String源码,看完你学会了吗?

    前言 最近花了两天时间,整理了一下String的源码.这个整理并不全面但是也涵盖了大部分Spring源码中的方法.后续如果有时间还会将剩余的未整理的方法更新到这篇文章中.方便以后的复习和面试使用.如果 ...

  2. 让mac电脑更简单运行Windows软件的CrossOver,优势知多少?

    如今,一些iPhone和iPad机型拥有Face ID功能,此功能作用允许用户通过面部识别来解锁设备.该功能还不能在Mac上使用,但是国外媒体于7月27日报道称,在公测第三版的macOS Big Su ...

  3. C++基础知识篇:C++ 基本语法

    C++ 基本语法 C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互.现在让我们简要地看一下什么是类.对象,方法.即时变量. 对象 - 对象具有状态和行为.例如:一只狗的状态 - 颜 ...

  4. Memtest在CentOS下的使用方法。

    #memtest,指定测试大小范围248G,指定测试1次 nohup memtester 248G 1 > mem218.log&

  5. Lsi卡和IB卡在CentOS中升级

    LSI 9271 步骤1:准备升级工具和固件包 rpm -ivh MegaCli-8.07.14-1.noarch.rpm [root@phegdata01 ~]# unzip 23-34-0-000 ...

  6. 基于gin的golang web开发:认证利器jwt

    JSON Web Token(JWT)是一种很流行的跨域认证解决方案,JWT基于JSON可以在进行验证的同时附带身份信息,对于前后端分离项目很有帮助. eyJhbGciOiJIUzI1NiIsInR5 ...

  7. 「刷题笔记」LCA问题相关

    板子 ll lg[40]; ll dep[N],fa[N][40]; ll dis[N]; void dfs(ll u,ll f) { dep[u]=dep[f]+1; fa[u][0]=f; for ...

  8. 单体->集群->模块化->分布式微服务

    开头语: 每篇一段开头语,在技术的道路中寻找文采的乐趣.(如果随笔中都是大白话勿喷,兄弟姐妹们) 单体项目 单体项目适用于小型开发,或自己来进行小项目的测试和使用. 单体项目的缺憾 多人开发项目所出现 ...

  9. 20200203_windows2012下安装mysql 5.7.29

    一.   检查系统版本: 二. 下载mysql, 下载地址: https://dev.mysql.com/downloads/mysql/5.7.html#downloads 三.   解压下载后的压 ...

  10. 老猿Python博文汇总目录--按标题排序

    ☞ ░ 前往老猿Python博文目录 ░ 本部分为老猿CSDN全部博文的汇总(含转载部分),所有文章在此未进行归类,仅按文章标题排序,方便关键字查找.本部分内容将至少以周为单位定期更新,可能不包含发布 ...