[51nod1040]最大公约数之和

Description

i=1ngcd(i,n)

n<=10^9

Solution

这道题有多种做法。
我们设 f(n)=ni=1gcd(i,n)
那么f应该是积性函数。(证明自行脑补)
也就是说我们要求出来 f(pk)p
直接推式子似乎很麻烦,我们换个思路。
如何从 f(pk) 转移到 f(pk+1) ?
首先,因为我们可以把f(p^k)*p,那么就构成了f(p^k+1)的答案中所有不为1的部分.
(显然 gcd(i,p)=gcd(ip,p2)p
那么剩下的为1的就是 φ(pk+1) 了。
于是我们得到了

f(pk+1)=f(pk)p+φ(pk+1)

于是就解决了。

然而,我发现似乎只有我一个人想用积性函数的方法。
其余的都是机智的直接 φ 法。
因为我们的答案都是n的因数。那么我们把它分解质因数,枚举每个因数x,我们就是要求1~n有多少个数k满足 gcd(x,k)=x 很显然有 φ(nx) 个。
于是暴力求 φ 也可以。

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
ll ans;
int a[32],b[32],n;
int main() {
    scanf("%d",&n);int i=2;ans=1;
    fo(i,2,sqrt(n)) {
        if (!(n%i)) a[++a[0]]=i;
        while (!(n%i)) b[a[0]]++,n/=i;
    }
    if (n>1) a[++a[0]]=n,b[a[0]]=1;
    fo(i,1,a[0]) {
        ll sum=1,x=1;
        fo(j,1,b[i]) sum=sum*a[i]+x*(a[i]-1),x*=a[i];
        ans*=sum;
    }
    printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值