CF1717E 题解
huge现场提供水题。口胡了十分钟搞了一个 \(O(n\log^2n)\) 的退化做法。。
然后char_phi先生让我写篇题解我就来写了。顺便水博客玩。轻喷
首先我们看这个式子:
\[\sum_{a+b+c=n}\rm{lcm}(c,\gcd(a,b))
\]
套路枚举 \(\gcd\) :
\[\sum_{d=1}\sum_{a+b+c=n}\rm{lcm}(c,d)[\gcd(a,b)=d]
\]
\[\sum_{d=1}\sum_{c=n-a-b}\rm{lcm}(c,d)[\gcd(a,b)=d]
\]
然后我们观赏一下后边那一堆东西什么时候有贡献。如果 \(\gcd(a,b)=d\) ,显然 \(\gcd(\frac ad,\frac bd)=1\) 。又因为 \(a+b=n-c\) ,所以 \(\frac{a+b}d=\frac{n-c}d\) 。也就是说,后面的东西的贡献是:
\[\sum_{a=1}^{\frac{n-c}d}[\gcd(a,\frac{n-c}d-a)=1]
\]
辗转相减,右边 \(+a\) ,得到
\[\sum_{a=1}^{\frac{n-c}d}[\gcd(a,\frac{n-c}d)=1]
\]
发现这个就是 \(\varphi(\frac{n-c}d)\) 。显然当且仅当 \(d|n-c\) 时产生贡献。所以原来的式子就变成了
\[\sum_{d=1}\sum_{c=n-a-b}\rm{lcm}(c,d)\varphi(\frac{n-c}d)[d|n-c]
\]
所以直接枚举 \(d\) 的倍数作为 \(n-c\) 然后暴力求就行了。枚举倍数一个 \(\log\) ,暴力 \(\gcd\) 一个 \(\log\) ,总共 \(O(n\log^2n)\) ,能过。
还有这个题 \(\varphi(1)=0\) 。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
const int mod=1000000007;
int ans,n,p[300010],phi[300010];
bool v[300010];
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int lcm(int a,int b){
return 1ll*a*b/gcd(a,b)%mod;
}
void get(int n){
for(int i=2;i<=n;i++){
if(!v[i]){
p[++p[0]]=i;phi[i]=i-1;
}
for(int j=1;j<=p[0]&&i*p[j]<=n;j++){
v[i*p[j]]=true;
if(i%p[j]==0){
phi[i*p[j]]=phi[i]*p[j];break;
}
phi[i*p[j]]=phi[i]*phi[p[j]];
}
}
}
int main(){
scanf("%d",&n);
get(n);
for(int d=1;d<=n;d++){
for(int i=d;i<=n;i+=d){
int ret=n-i;
ans=(ans+1ll*lcm(ret,d)*phi[i/d]%mod)%mod;
}
}
printf("%d\n",ans);
}
虽然但是我还没改完题我不知道我在这干啥子。
快踩