您的位置:首页 > 其它

【BZOJ4802】【Pollard-Rho模板题】欧拉函数

2018-02-26 14:21 375 查看

Description

给定n(n≤1018)n(n≤1018),求φ(n)φ(n)

Solution

直接用Pollard-Rho分解质因数,然后用φ(n)=n∏(1−1pi)φ(n)=n∏(1−1pi)(pipi表示nn的不同质因数)

Source

/************************************************
* Au: Hany01
* Date: Feb 26th, 2018
* Prob: BZOJ4802
* Email: hany01@foxmail.com
************************************************/

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define fir first
#define sec second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia
#define Times (10)

template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

inline void File()
{
#ifdef hany01
freopen("bzoj4802.in", "r", stdin);
freopen("bzoj4802.out", "w", stdout);
#endif
}

LL d[100];
int cnt;

LL gcd(LL x, LL y) { return x ? gcd(y % x, x) : y; }

LL mult(LL a, LL b, LL Mod)
{
LL Ans = 0;
for (a %= Mod; b; b >>= 1, a = (a + a) % Mod) if (b & 1) (Ans += a) %= Mod;
return Ans;
}

LL Pow(LL a, LL b, LL Mod)
{
LL Ans = 1;
for (a %= Mod; b; b >>= 1, a = mult(a, a, Mod)) if (b & 1) Ans = mult(Ans, a, Mod);
return Ans;
}

bool MillerRabin(LL n)
{
if (n < 2 && (n & 1) == 0) return 0;
if (n == 2) return 1;
register LL m = n - 1;
register int cnt = 0;
while ((m & 1) == 0) m >>= 1, ++ cnt;
rep(T, Times) {
register LL a = rand() % (n - 1) + 1, t = Pow(a, m, n), tt;
For(i, 1, cnt) {
tt = mult(t, t, n);
if (tt == 1 && t != 1 && t != n - 1) return 0;
t = tt;
}
if (t != 1) return 0;
}
return 1;
}

inline LL PollardRho(LL n, LL c)
{
LL x, y, tmp, i = 1, k = 2;
x = y = rand() % (n - 1) + 1;
for ( ; ; ) {
++ i, x = (mult(x, x, n) + c) % n;
tmp = gcd(abs(x - y), n);
if (tmp > 1 && tmp < n) return tmp;
if (x == y) return n;
if (i == k) y = x, k <<= 1;
}
}

void find(LL n, int c)
{
if (n == 1) return;
if (MillerRabin(n)) { d[++ cnt] = n; return ; }
LL nn = n, k = c;
while (nn == n) nn = PollardRho(nn, c --);
find(nn, k);
find(n / nn, k);
}

int main()
{
File();
srand(19260817);
LL n, Ans;
scanf("%lld", &n);
find(n, 120);
Ans = n;
sort(d + 1, d + 1 + cnt);
cnt = unique(d + 1, d + 1 + cnt) - d - 1;
For(i, 1, cnt) Ans = Ans / d[i] * (d[i] - 1);
printf("%lld\n", Ans);
return 0;
}
//轮台九月风夜吼,一川碎石大如斗,随风满地石乱走。
//    -- 岑参《走马川行奉送出师西征》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: