洛谷P2303 [SDOI2012] Longge的问题

数论蒟蒻来写题解啦因为太弱所以只敢写在这里

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

思路:暴力枚举是不可能的,但是发现 n n n是一直存在的,那么答案只有可能是 n n n的约数,所以考虑枚举答案统计贡献。

那么我们把问题变成了

a n s = ∑ d ∣ n d × ∑ i = 1 n [ g c d ( i , n ) = d ] \qquad \qquad ans = \sum\limits_{d|n}d\times \sum\limits_{i=1}^{n}[gcd(i,n)=d] ans=dnd×i=1n[gcd(i,n)=d]
一起除个 d d d
a n s = ∑ d ∣ n d × ∑ i = 1 n [ g c d ( i d , n d ) = 1 ] \quad \qquad \qquad ans= \sum\limits_{d|n}d\times \sum\limits_{i=1}^{n}[gcd(\frac{i}{d},\frac{n}{d})=1] ans=dnd×i=1n[gcd(di,dn)=1]
i i i的那个除号提出来
a n s = ∑ d ∣ n d × ∑ i = 1 n d [ g c d ( i , n d ) = 1 ] \qquad \qquad \quad ans= \sum\limits_{d|n}d\times \sum\limits_{i=1}^{\frac{n}{d}}[gcd(i,\frac{n}{d})=1] ans=dnd×i=1dn[gcd(i,dn)=1]
应该很好理解吧。

然后我们发现:这不就是欧拉函数吗???
a n s = ∑ d ∣ n d × ϕ ( n d ) ans=\sum\limits_{d|n}d\times \phi(\frac{n}{d}) ans=dnd×ϕ(dn)

然后复杂度不会用 O O O写,大概就是 ( ∑ d ∣ n d ) (\sum\limits_{d|n}\sqrt{d}) (dnd )+ n \sqrt{n} n

实际上跑得飞快。

如果你还想优化,可以预处理 n \sqrt{n} n 以内的质数,优化 d \sqrt{d} d 的那部分复杂度。

c o d e code code

#include<bits/stdc++.h>
using namespace std;
#define int long long
int euler(int a){
	int ans=a;
	for(int i=2;i*i<=a;++i)
		if(a%i==0){
			ans=ans/i*(i-1);
			while(a%i==0)a/=i;
		}
	if(a!=1)ans=ans/a*(a-1);
	return ans;
}
int n,ans;
signed main(){
	scanf("%lld",&n);
	for(int i=1;i*i<=n;++i)
		if(n%i==0){
			ans+=i*euler(n/i);
			if(i!=n/i) ans+=(n/i)*euler(i);
		}
	printf("%lld",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值