[洛谷]P3768 简单的数学题-数论

题目地址

题意简述

给定两个整数 n , p n,p n,p,求下面式子的值:

∑ i = 1 n ∑ j = 1 n i j ( g c d ( i , j ) ) \sum_{i=1}^n\sum_{j=1}^nij(gcd(i,j)) i=1nj=1nij(gcd(i,j))

在模 p p p意义下的值。

n ≤ 1 0 10 , p ≤ 1.1 × 1 0 9 n\leq 10^{10},p\leq 1.1\times 10^9 n1010,p1.1×109 p p p为质数。


  • 分析

我们根据套路,来枚举 g c d gcd gcd,原式变成:

∑ d = 1 n ∑ i = 1 n ∑ j = 1 n i j d [ g c d ( i , j ) = d ] = ∑ d = 1 n d ∑ i = 1 n ∑ j = 1 n i j [ g c d ( i , j ) = d ] = ∑ d = 1 n d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ n d ⌋ i d × j d [ g c d ( i , j ) = 1 ] = ∑ d = 1 n d 3 ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ n d ⌋ i j [ g c d ( i , j ) = 1 ] \sum_{d=1}^n\sum_{i=1}^n\sum_{j=1}^nijd[gcd(i,j)=d]\\ =\sum_{d=1}^nd\sum_{i=1}^n\sum_{j=1}^nij[gcd(i,j)=d]\\ =\sum_{d=1}^nd\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}id\times jd[gcd(i,j)=1]\\ =\sum_{d=1}^nd^3\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}ij[gcd(i,j)=1] d=1ni=1nj=1nijd[gcd(i,j)=d]=d=1ndi=1nj=1nij[gcd(i,j)=d]=d=1ndi=1dnj=1dnid×jd[gcd(i,j)=1]=d=1nd3i=1dnj=1dnij[gcd(i,j)=1]

后面我们用莫比乌斯反演的套路,原式变成:

= ∑ d = 1 n d 3 ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ n d ⌋ i j ∑ w ∣ i , w ∣ j μ ( w ) = ∑ d = 1 n d 3 ∑ w = 1 ⌊ n d ⌋ μ ( w ) ∑ i = 1 ⌊ n d w ⌋ i w ∑ j = 1 ⌊ n d w ⌋ j w = ∑ d = 1 n d 3 ∑ w = 1 ⌊ n d ⌋ μ ( w ) w 2 ∑ i = 1 ⌊ n d w ⌋ i ∑ j = 1 ⌊ n d w ⌋ j = \sum_{d=1}^nd^3\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}ij\sum_{w|i,w|j}\mu(w)\\ = \sum_{d=1}^nd^3\sum_{w=1}^{\lfloor\frac{n}{d}\rfloor}\mu(w)\sum_{i=1}^{\lfloor\frac{n}{dw}\rfloor}iw\sum_{j=1}^{\lfloor\frac{n}{dw}\rfloor}jw\\ = \sum_{d=1}^nd^3\sum_{w=1}^{^{\lfloor\frac{n}{d}\rfloor}}\mu(w)w^2\sum_{i=1}^{\lfloor\frac{n}{dw}\rfloor}i\sum_{j=1}^{\lfloor\frac{n}{dw}\rfloor}j =d=1nd3i=1dnj=1dnijwi,wjμ(w)=d=1nd3w=1dnμ(w)i=1dwniwj=1dwnjw=d=1nd3w=1dnμ(w)w2i=1dwnij=1dwnj

然后我们令 S ( n ) = n × ( n + 1 ) 2 S(n)=\frac{n\times (n+1)}{2} S(n)=2n×(n+1),原式为:

= ∑ d = 1 n d 3 ∑ w = 1 ⌊ n d ⌋ μ ( w ) w 2 S ( ⌊ n d w ⌋ ) S ( ⌊ n d w ⌋ ) = \sum_{d=1}^nd^3\sum_{w=1}^{^{\lfloor\frac{n}{d}\rfloor}}\mu(w)w^2S(\lfloor\frac{n}{dw}\rfloor)S(\lfloor\frac{n}{dw}\rfloor) =d=1nd3w=1dnμ(w)w2S(dwn)S(dwn)

但是此时 O ( n n ) O(n\sqrt{n}) O(nn )的做法显然不行,所以根据套路,我们转换枚举 d w dw dw,令 T = d w T=dw T=dw,原式可以变成:

= ∑ T = 1 n S ( ⌊ n T ⌋ ) 2 ∑ d ∣ T d 3 μ ( T d ) ( T d ) 2 = ∑ T = 1 n S ( ⌊ n T ⌋ ) 2 ∑ d ∣ T d T 2 μ ( T d ) = ∑ T = 1 n S ( ⌊ n T ⌋ ) 2 T 2 ∑ d ∣ T d μ ( T d ) =\sum_{T=1}^nS\left(\lfloor\frac{n}{T}\rfloor\right)^2\sum_{d|T}d^3\mu\left(\frac{T}{d}\right)\left(\frac{T}{d}\right)^2\\ = \sum_{T=1}^nS\left(\lfloor\frac{n}{T}\rfloor\right)^2\sum_{d|T}dT^2\mu\left(\frac{T}{d}\right)\\ = \sum_{T=1}^nS\left(\lfloor\frac{n}{T}\rfloor\right)^2T^2\sum_{d|T}d\mu\left(\frac{T}{d}\right) =T=1nS(Tn)2dTd3μ(dT)(dT)2=T=1nS(Tn)2dTdT2μ(dT)=T=1nS(Tn)2T2dTdμ(dT)

我们可以发现,最后那一部分就是 i d ⨂ μ = φ id\bigotimes \mu=\varphi idμ=φ ⨂ \bigotimes 为狄利克雷卷积,其中因为 φ ⨂ 1 = i d \varphi\bigotimes1=id φ1=id,所以 φ ⨂ 1 ⨂ μ = i d ⨂ μ \varphi\bigotimes 1\bigotimes \mu = id \bigotimes \mu φ1μ=idμ,而 μ ⨂ 1 = ϵ ( 单 位 元 ) \mu \bigotimes 1= \epsilon(单位元) μ1=ϵ(),所以 φ ⨂ ϵ = φ = i d ⨂ μ \varphi\bigotimes \epsilon=\varphi=id\bigotimes \mu φϵ=φ=idμ,其中 i d ( i ) = i id(i)=i id(i)=i)。

所以原式变成了:

= ∑ T = 1 n S ( ⌊ n T ⌋ ) 2 T 2 φ ( T ) = \sum_{T=1}^nS\left(\lfloor\frac{n}{T}\rfloor\right)^2T^2\varphi(T) =T=1nS(Tn)2T2φ(T)

接下来,前面的 S S S可以数论分块 O ( n ) 的 求 , 而 后 面 需 要 前 缀 和 , 而 O(\sqrt{n})的求,而后面需要前缀和,而 O(n )n$很大不能线性筛出,所以我们只能用低于线性的杜教筛来求。

我们令 F ( n ) = ∑ i = 1 n i 2 φ ( i ) F(n)=\sum_{i=1}^ni^2\varphi(i) F(n)=i=1ni2φ(i),换一种写法就是:
F ( n ) = ∑ i = 1 n i d 2 φ ( i ) F(n)=\sum_{i=1}^nid^2\varphi(i) F(n)=i=1nid2φ(i)

由于 i d k ⨂ i d k ( n ) = ∑ d ∣ n i d k ( d ) i d k ( n d ) = n k ∑ d ∣ n 1 id^k\bigotimes id^k(n)=\sum\limits_{d|n}id^k(d)id^k(\frac{n}{d})=n^k\sum_{d|n}1 idkidk(n)=dnidk(d)idk(dn)=nkdn1

所以我们令 f ( n ) = n 2 φ ( n ) , g ( n ) = n 2 f(n)=n^2\varphi(n),g(n)=n^2 f(n)=n2φ(n),g(n)=n2,那么:
f ⨂ g ( n ) = ∑ d ∣ n φ ( d ) d 2 n 2 d 2 = n 2 ∑ d ∣ n φ ( d ) f\bigotimes g(n)=\sum_{d|n}\varphi(d)d^2\frac{n^2}{d^2}\\ = n^2\sum_{d|n}\varphi(d) fg(n)=dnφ(d)d2d2n2=n2dnφ(d)

由于 ∑ d ∣ n φ ( d ) = n \sum_{d|n}\varphi(d)=n dnφ(d)=n,所以 f ⨂ g = i d 3 f\bigotimes g=id^3 fg=id3

套入杜教筛公式,我们可以得到:

F ( n ) = ∑ i = 1 n i 3 − ∑ i = 2 n i 2 F ( n i ) F(n)=\sum_{i=1}^ni^3-\sum_{i=2}^ni^2F(\frac{n}{i}) F(n)=i=1ni3i=2ni2F(in)

根据公式 ∑ i = 1 n i 3 = ( n × ( n + 1 ) 2 ) 2 \sum_{i=1}^ni^3=\left(\frac{n\times(n+1)}{2}\right)^2 i=1ni3=(2n×(n+1))2

∑ i = 1 n i 2 = n × ( n + 1 ) × ( 2 n + 1 ) 6 \sum_{i=1}^ni^2=\frac{n\times(n+1)\times(2n+1)}{6} i=1ni2=6n×(n+1)×(2n+1)

所以每次用杜教筛算前缀和即可。

复杂度大概为 O ( n + 2 n 2 3 ) O(\sqrt{n}+2n^{\frac{2}{3}}) O(n +2n32)

下面上代码:

#include
#include
#include
#include
#define ll long long
using namespace std;
const int M=12000001,N=1e4+1;
ll n,P;
ll A[M],B[N],F[M];
ll prime[N],phi[M],cnt,inv_2,inv_6;
bool vis[M];
ll Sqr(ll a){return a*a%P;}
ll fpow(ll a,ll b){
	ll ans=1;
	for(;b;b>>=1,a=(a*a)%P){
		if(b&1)ans=(ans*a)%P;
	}
	return ans;
}
void init(ll w){
    phi[1]=1;
    inv_2=fpow(2,P-2);
    inv_6=fpow(6,P-2);
    for(ll i=2;i<=w;i++){
        if(!vis[i])prime[++cnt]=i,phi[i]=i-1;
        for(ll j=1,v;j<=cnt&&i*prime[j]<=w;j++){
            v=i*prime[j];
            vis[v]=1;
            if(!(i%prime[j])){
                phi[v]=phi[i]*prime[j];
                break;
            }
            phi[v]=phi[i]*phi[prime[j]];
        }
    }
    A[0]=0;
    for(int i=1;i<=w;i++)A[i]=(A[i-1]+Sqr(i)*phi[i]%P)%P;
}
ll &Rec(ll a){
    if(a<M) return A[a];
    else return B[n/a];//不用map,储存空间的小技巧
}
ll S(ll x){if(x>=P)x%=P;return (x*(x+1)%P)*inv_2%P;}
ll S2(ll x){if(x>=P)x%=P;return ((x*(x+1))%P)*((x+x+1)%P)%P*inv_6%P;}
ll SS(ll L,ll R){return (S(R)-S(L-1))%P;}
ll SS2(ll L,ll R){return (S2(R)-S2(L-1))%P;}
ll S3(ll x){return Sqr(S(x));}
ll calc(ll x){
    if(!x) return 0;
    ll &ans=Rec(x);
    if(ans!=-1) return ans;
    ans=S3(x);
    for(ll i=2,j;i<=x;i=j+1){
        j=x/(x/i);
        (ans-=SS2(i,j)*calc(x/i))%=P;
    }
    return (ans+P)%P;
}
ll area(ll L,ll R){
    return ((calc(R)-calc(L-1))%P+P)%P;
}
ll solve(){
    ll ans=0;
    for(ll i=1,j;i<=n;i=j+1){
        j=n/(n/i);
        (ans+=Sqr(S(n/i))*area(i,j)%P)%=P;
    }
    return (ans+P)%P;
}
int main(){
    memset(A,-1,sizeof(A));
    memset(B,-1,sizeof(B));
    scanf("%lld%lld",&P,&n);
    init(min(n,M-1ll));
    printf("%lld\n",solve());
    return 0;
}

你可能感兴趣的:(题解,OI数论)