[bzoj]2705: [SDOI2012]Longge的问题[数论][数学][欧拉函数][gcd]

[bzoj]P2705 OR [luogu]P2303

Longge的问题

Description

Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。

Input

一个整数,为N。

Output

一个整数,为所求的答案。

Sample Input

6

Sample Output

15

HINT

【数据范围】

对于60%的数据,0<N<=2^16。

对于100%的数据,0<N<=2^32。


注意到这些最大公约数肯定是n的约数,对于约数K,我们想找出gcd(n,i)=k的有多少个,也即gcd(n/k,i/k)=1,也就等价于求φ(n/k)。

ans=Σφ(n/k)*k

问题就在于怎么求φ(n),之前竟然一直不知道可以sqrt(n)计算,感觉自己好傻,今天学习了...(一直以为要用递推,不然就要写线性筛[神经病啊])

还有就是枚举sqrt(n)时注意k*k=n的情况,没判这种情况结果bzoj过了,luogu没过...很尴尬。

代码:

 1 //2017.10.31
 2 //math
 3 #include<iostream>
 4 #include<cstdio>
 5 #include<cstring>
 6 using namespace std;
 7 typedef long long ll ;
 8 inline ll read();
 9 namespace lys{
10     ll n,ans;
11     ll phi(ll x){
12         int i;
13         ll w=x,res=x;
14         for(i=2;1LL*i*i<=w;i++){
15             if(!(x%i)){
16                 res=res*(i-1)/i;
17                 while(!(x%i)) x/=i;
18             }
19         }
20         if(x>1) res=res*(x-1)/x;
21         return res ;
22     }
23     int main(){
24         int i;
25         n=read();
26         for(i=1;1LL*i*i<=n;i++)
27             if(!(n%i)){
28                 ans+=phi(n/i)*i;
29                 if(1LL*i*i!=n) ans+=phi(i)*(n/i);
30             }
31         printf("%lld
",ans);
32         return 0;
33     }
34 }
35 int main(){
36     lys::main();
37     return 0;
38 }
39 inline ll read(){
40     ll kk=0,ff=1;
41     char c=getchar();
42     while(c<'0'||c>'9'){
43         if(c=='-') ff=-1;
44         c=getchar();
45     }
46     while(c>='0'&&c<='9') kk=kk*10+c-'0',c=getchar();
47     return kk*ff;
48 }
原文地址:https://www.cnblogs.com/_inx/p/7763658.html