数论——51nod1040 最大公约数之和

来源:互联网 发布:局域网监控软件 编辑:程序博客网 时间:2024/05/20 09:08

题面:51nod1040
这篇题解只是为了纪念一下好久没有刷数论题的我终于又刷了一道数论水题的题解
初一看没有思路(我是数学蒟蒻QAQ)后来发现可以算贡献。。。
我们发现本质上是让我们求gcd(n,i)=x的数目(x是n的因数)再乘上x就可以了
那么如何求gcd(n,i)=x的数目呢?其实呢gcd(n,i)=x的数目就是gcd(n/x,i/x)=1的数目
然后发现gcd(n/x,i/x)=1的数目就是phi(n/x)
然后就大力求phi就可以了。。。(顺便唤醒我求单点phi的记忆)

#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#include <ctime>#include <map>#include <queue>#include <cstdlib>#include <string>#include <climits>#include <set>#include <vector>#define int long longusing namespace std;inline int read(){    int k=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();}    return k*f;}inline int phi(int x){    int ans=x;    for(int i=2;i*i<=x;i++)if(x%i==0){        ans=ans/i*(i-1);        while(x%i==0)x/=i;    }    if(x>1)ans=ans/x*(x-1);    return ans;}signed main(){    int n=read(),ans=0;    if(n==1)return puts("1")&0;    for(int i=1;i*i<=n;i++)if(n%i==0){        if(i!=n/i)ans+=phi(i)*(n/i)+phi(n/i)*i;        else ans+=phi(i)*(n/i);    }    printf("%lld",ans);    return 0;}
原创粉丝点击