当前位置: 代码迷 >> 综合 >> 洛谷P2303 [SDOI2012] Longge的问题
  详细解决方案

洛谷P2303 [SDOI2012] Longge的问题

热度:22   发布时间:2023-12-14 10:09:22.0

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

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

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

那么我们把问题变成了

ans=∑d∣nd×∑i=1n[gcd(i,n)=d]\qquad \qquad ans = \sum\limits_{d|n}d\times \sum\limits_{i=1}^{n}[gcd(i,n)=d]ans=dn?d×i=1n?[gcd(i,n)=d]
一起除个ddd
ans=∑d∣nd×∑i=1n[gcd(id,nd)=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=dn?d×i=1n?[gcd(di?,dn?)=1]
iii的那个除号提出来
ans=∑d∣nd×∑i=1nd[gcd(i,nd)=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=dn?d×i=1dn??[gcd(i,dn?)=1]
应该很好理解吧。

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

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

实际上跑得飞快。

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

codecodecode

#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;
}