Typesetting math: 100%

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

Description

已知N,求phi(N)

Input

正整数N。N<=10^18

Output

输出phi(N)

Sample Input

8

Sample Output

4

Solution

一开始读错题了……以为是求约束个数和……

读对题之后然后发现我不会就问旁边的宽嫂……

宽嫂:这不是欧拉函数的定义式么?我初中就会了啊。

我:

然后去百度了一发,发现一个数的欧拉函数就是

(pi1)pki1i,其中pi是这个数的质因子,ki是这个质因子的次数……

然后套板子就行了。

发现我之前抄了个假的快速乘然后还花了我一会儿改代码+改博客……QAQ

Code

复制代码
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<map>
 5 #include<algorithm>
 6 #define LL long long
 7 using namespace std;
 8 
 9 LL n,ans=1,Num[109],cnt;
10 LL prime[15]={2,3,5,7,11,13,17,19,23,29,31};
11 map<LL,LL>Keg;
12 
13 LL Mul(LL a,LL b,LL MOD)
14 {
15     LL tmp=a*b-(LL)((long double)a*b/MOD+0.1)*MOD;
16     return tmp<0?tmp+MOD:tmp;
17 }
18 
19 LL Qpow(LL a,LL b,LL MOD)
20 {
21     LL ans=1;
22     while (b)
23     {
24         if (b&1) ans=Mul(ans,a,MOD);
25         a=Mul(a,a,MOD); b>>=1;
26     }
27     return ans;
28 }
29 
30 LL gcd(LL a,LL b) {return b==0?a:gcd(b,a%b);}
31 
32 bool Miller_Rabin(LL n)
33 {
34     if (n==2) return 1;
35     if (n<2 || n%2==0) return 0;
36     LL m=n-1,l=0;
37     while (m%2==0) m>>=1, l++;
38     for (int i=0; i<11; ++i)
39     {
40         LL p=prime[i],w=Qpow(p,m,n);
41         if (w==n-1 || w==1 || p==n) continue;
42         for (int j=1; j<=l; ++j)
43         {
44             LL u=Mul(w,w,n);
45             if (u==1 && w!=n-1 && w!=1) return 0;
46             w=u;
47         }
48         if (w!=1) return 0;
49     }
50     return 1;
51 }
52 
53 LL Pollard_Rho(LL n,LL c)
54 {
55     LL x=(rand()+1)%n,y=x,p=1,k=2;
56     for (LL i=1; p==1; ++i)
57     {
58         x=(Mul(x,x,n)+c)%n;
59         p=x>y?x-y:y-x;
60         p=gcd(p,n);
61         if (i==k) y=x, k=k+k;
62     }
63     return p;
64 }
65 
66 void Solve(LL n)
67 {
68     if (n==1) return;
69     if (Miller_Rabin(n))
70     {
71         if (!Keg[n]) Num[++cnt]=n;
72         ++Keg[n]; return;
73     }
74     LL t=n;
75     while (t==n) t=Pollard_Rho(n,rand()%(n-1)+1);
76     Solve(t); Solve(n/t);
77 }
78 
79 int main()
80 {
81     scanf("%lld",&n);
82     Solve(n);
83     for (int i=1; i<=cnt; ++i)
84         ans=ans*(Num[i]-1)*Qpow(Num[i],Keg[Num[i]]-1,2e18);
85     printf("%lld\n",ans);
86 }
复制代码
posted @   Refun  阅读(230)  评论(0编辑  收藏  举报
编辑推荐:
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
阅读排行:
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· 一个基于 .NET 开源免费的异地组网和内网穿透工具
· 《HelloGitHub》第 108 期
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单
点击右上角即可分享
微信分享提示