码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-06-24 13:04:24      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:while   +=   std   溢出   自己   span   水题   long   class   

题目: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;
}

 

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

标签:while   +=   std   溢出   自己   span   水题   long   class   

原文地址:https://www.cnblogs.com/Zinn/p/9220095.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!