【bzoj4802】尤拉函式
阿新 • • 發佈:2018-11-19
題目連結
想瞎搞過去的可能就只有我一個。。。。。
正解Pollard_rho演算法(啥rho演算法?)
Pollard_rho演算法是專門解決這類大數質因數分解的,當然還要搭配Miller_Rabin判素數(推薦一篇入門博文)
先質因數分解,然後按 的式子算就行了
程式碼:
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const int INF = 2147483647 ;
const int maxn = 10000000;
LL ans;
LL n,pri[maxn],tot,tme = 0;
inline LL getint()
{
LL ret = 0,f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') ret = ret * 10 + c - '0',c = getchar();
return ret * f;
}
inline LL mul(LL x,LL y,LL mod)
{
LL tmp=(x*y-(LL)((long double)x/mod*y+1.0e-8)*mod);
return tmp<0 ? tmp+mod : tmp;
}
inline LL qpow(LL a,LL b,LL n)
{
LL ret = 1;
while (b)
{
if (b & 1) ret = mul(ret,a,n);
a = mul(a,a,n);
b >>= 1;
}
return ret;
}
inline int miller(LL n)
{
int test;
if (n == 3)
test = 1;
if (n == 2) return 1;
if (n < 2 || n % 2 == 0) return 0;
LL m = n - 1,k = 0;
while (m % 2 == 0) m >>= 1 , k++;
for (int I = 1; I <= 5; I++)
{
LL a = rand() % (n - 1) + 1,b;
a = qpow(a,m,n);
for (int i = 1; i <= k; i++)
{
b = mul(a,a,n);
if (b == 1 && a != n - 1 && a != 1) return 0;
a = b;
}
if (a != 1) return 0;
}
return 1;
}
inline LL gcd(LL a,LL b)
{
return !b ? a : gcd(b,a % b);
}
inline LL rho(LL n)
{
LL x = rand() % (n - 1) + 1,y = x;
LL c = tme % (n - 1) + 1,g,k = 2,i = 0;
tme++;
while (233)
{
x = (mul(x,x,n) + c) % n;
if (x == y) return n;
g = gcd(abs(x - y),n);
if (g != 1) return g;
if (++i == k)
y = x , k <<= 1;
}
}
inline void split(LL n)
{
if (n == 1) return;
if (miller(n)) {pri[++tot] = n; return;}
LL p = n;
while (p == n) p = rho(p);
split(n / p);
split(p);
}
int main()
{
#ifdef AMC
freopen("AMC1.txt","r",stdin);
#endif
n = getint();
split(n);
sort(pri + 1,pri + tot + 1);
ans = 1;
for (int i = 1; i <= tot; i++)
{
if (pri[i] != pri[i - 1]) ans *= pri[i] - 1;
else ans *= pri[i];
}
printf("%lld\n",ans);
return 0;
}