bzoj2705 [SDOI2012]Longge的问题——因数

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2705

一开始自己想了半天...

有了点思路:遍历 n 的因数 k,每个因数要预处理出 gcd 等于这个因数的数的个数 s[k];

预处理过程中还要去重:s[k] = (n-1) / k , s[k] -= s[2*k] + s[3*k] +......,&(*%$^&...

正要勇猛去写的时候还是点开了TJ,然后被自己的愚蠢暴击...

考虑 gcd ( n , m ) = k 的 m 的个数,发现 gcd ( n/k , m/k ) = 1,也就是 phi ( n/k )!!!

所以遍历因数,求它们的欧拉函数;

但范围太大了不能预处理,所以暴力每次求;

然而发现自己暴力也不会了,想了许多纯纯的暴力...

还是要用公式的啊... phi (x) = x * ∏ ( 1 - 1 / p[i] );

总之,就是一道关于欧拉函数的水题...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
ll n,ans;
ll phi(ll x)
{
    ll ret=x;
    for(int i=2;i*i<=x;i++)
        if(x%i==0)
        {
            ret=ret/i*(i-1);//防止溢出
            while(x%i==0)x/=i; 
        }
    if(x>1) ret=ret/x*(x-1);
    return ret;
}
int main()
{
    scanf("%lld",&n);
    for(int i=1;i*i<=n;i++)
        if(n%i==0)
        {
            ans+=i*phi(n/i);
            if(i*i<n) ans+=n/i*phi(i);//别算2遍 sqrt(n) 
        }
    printf("%lld",ans);
    return 0;
}

 

posted @ 2018-06-24 12:08  Zinn  阅读(125)  评论(0编辑  收藏  举报