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

虽然但是我还没改完题我不知道我在这干啥子。

posted @ 2022-10-12 19:40  gtm1514  阅读(34)  评论(0编辑  收藏  举报