51nod1584加权约数和

Posted zh-comld

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1584加权约数和相关的知识,希望对你有一定的参考价值。

题目大意:

求:
\[ \sum_i-1^n\sum_j=1^nmax(i,j)\sigma(i*j) \]

题解

对于这个\(\max\),套路的把它转化成:
\[ 2*\sum_i=1^n\sum_j=1^ii*\sigma(i*j)-\sum_i=1^n i*\sigma(i*i) \]
对于前面的部分,我们可以:
\[ \sum_i=1^n\sum_j=1^ii\sum_a|i\sum_b|ja*\fracjb[(a,b)==1] \]

\[ \sum_i=1^ni\sum_j=i^n\sum_a|i\sum_b|ja*\fracjb\sum_d|(i,j)\mu(d) \]

\[ \sum_d=1^n\mu(d)\sum_i=1^\fracndi*d\sum_a|ia*d\sum_j=1^i\sum_b|j\fracjb \]

\[ \sum_d=1^n\mu(d)d^2\sum_i=1^\fracndi\sum_a|ia\sum_j=1^i\sum_b|j\fracjb \]

\[ \sum_d=1^n\mu(d)d^2\sum_i=1^\fracndg_i \]

\[ \sum_D=1^n\sum_d|D\mu(d)d^2G_D/d \]

\[ g_n=n*\sigma_n*\sum_i=1^n \sigma_i \]

这个\(g\)数组就可以线性预处理了。

后面的部分可以线性筛,姿势++。

代码

#include<bits/stdc++.h>
#define N 1000009
using namespace std;
typedef long long ll;
const int maxn=1000000;
const int mod=1000000007;
bool vis[N];
int prime[N];
ll mu[N],md[N],mdp[N],ans[N],g[N],sum[N],f[N];
ll sig[N],sig2[N];
inline ll rd()
    ll x=0;char c=getchar();bool f=0;
    while(!isdigit(c))if(c=='-')f=1;c=getchar();
    while(isdigit(c))x=(x<<1)+(x<<3)+(c^48);c=getchar();
    return f?-x:x;

inline void MOD(ll &x)x=x>=mod?x-mod:x;
inline void prework(int n)
    sig[1]=mu[1]=sig2[1]=md[1]=mdp[1]=1;
    for(int i=2;i<=n;++i)
        //cout<<i<<" "<<md[i]<<" "<<mdp[i]<<endl;
        if(!vis[i])
            prime[++prime[0]]=i;
            md[i]=mdp[i]=i;
            mu[i]=mod-1;
            sig[i]=i+1;
            sig2[i]=(1ll*i*i%mod+i+1)%mod;
        
        for(int j=1;j<=prime[0]&&(i*prime[j])<=n;++j)
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
                mu[i*prime[j]]=0;
                md[i*prime[j]]=prime[j];
                mdp[i*prime[j]]=mdp[i]*prime[j];
                sig[i*prime[j]]=(sig[i]+1ll*prime[j]*mdp[i]%mod*sig[i/mdp[i]]%mod)%mod;
                sig2[i*prime[j]]=sig2[i]+(1ll*mdp[i]*mdp[i]%mod*md[i]%mod+
                1ll*mdp[i]*mdp[i]%mod*md[i]%mod*md[i]%mod)*sig2[i/mdp[i]]%mod;
                sig2[i*prime[j]]%=mod;
                break;
            
            mu[i*prime[j]]=mod-mu[i];
            sig[i*prime[j]]=sig[i]*sig[prime[j]]%mod;
            md[i*prime[j]]=mdp[i*prime[j]]=prime[j];
            sig2[i*prime[j]]=sig2[i]*sig2[prime[j]]%mod;
        
    
    for(int i=1;i<=n;++i)MOD(sum[i]=sum[i-1]+sig[i]);
    for(int i=1;i<=n;++i)
        g[i]=1ll*sig[i]*i%mod*sum[i]%mod;
        MOD(sig2[i]=sig2[i-1]+sig2[i]*i%mod);
        for(int j=i;j<=n;j+=i)MOD(f[j]+=g[i]*mu[j/i]%mod*(j/i)%mod*(j/i)%mod);
        MOD(f[i]+=f[i-1]);
        ans[i]=(f[i]*2-sig2[i]+mod)%mod;
    

int main()
    prework(maxn);
    int T=rd(),ct=0;
    while(T--)
      int x=rd();ct++;
      printf("Case #%d: %lld\n",ct,ans[x]);
    
    return 0;

以上是关于51nod1584加权约数和的主要内容,如果未能解决你的问题,请参考以下文章

51nod - 1586 - 约数和 - 水题

51Nod-1586-约数和

51nod1586 约数和

51nod 约数和(数论)

51nod1220 约数之和

51nod 2456STL最小约数 V2