题目大意:给你n,求$\sum_{i=1}^{n}\sum_{j=i}^{n}[gcd(i,j)=1](i+1)(j+1)$

子任务一:暴力

子任务二:$T=50000,n≤10^7$

子任务三:$T=3,n≤10^{10}$

 

解法一:

我们化一下这个式子

$\sum_{i=1}^{n}\sum_{j=i}^{n}[gcd(i,j)=1](i+1)(j+1)$

$=\sum_{i=1}^{n}\sum_{j=i}^{n}\sum_{k|gcd(i,j)} \mu(k)(i+1)(j+1)$

$=\frac{1}{2}\bigg(4+\sum_{d=1}^{n}\sum_{i=1}^{Q}\sum_{j=1}^{Q}(di+1)(dj+1)\bigg)$其中$Q=\lfloor \frac{n}{d} \rfloor $,下面同理

$=\frac{1}{2}\bigg(4+\sum_{d=1}^{n}\mu(d)(Q^2+d(1+Q)Q^2+d^2(\frac{(1+Q)Q}{2})^2)\bigg)$

不难发现,这个式子可以预处理出$\mu(i)$的前缀和,然后通过根号分块的方法,实现单次$O(\sqrt{n})$时间复杂度的询问操作。在前两个子任务中,时间复杂度为$O(T\sqrt{n})$。

在第三个子任务中,我们采用杜教筛求$\mu$的前缀和,即可实现求得答案。

但是问题在于,该题单点的时限为15s,本蒟蒻经过大力卡常后,第二个子任务依然只能在17s左右跑出。

 

我们考虑换一个做法,还是刚才的式子

$\sum_{i=1}^{n}\sum_{j=i}^{n}[gcd(i,j)=1](i+1)(j+1)$

考虑到要让$gcd(i,j)=1$,那么在i不变的情况下,共有$\varphi(i)$个数,它们的和为$\frac{1}{2}i\times \varphi(i)$。

那么原式为:

$=\frac{1}{2}\sum_{i=1}^{n}(i+1)(i+2)\varphi(i)$

$=\frac{1}{2}\sum_{i=1}^{n}\bigg(2(i+1)\varphi(i)+i(i+1)\varphi(i) \bigg)$

$=\frac{1}{2}\bigg( 2\sum_{i=1}^{n}\varphi(i)+3\sum_{i=1}^{n}i\varphi(i)+\sum_{i=1}^{n}i^2\varphi(i) \bigg)$

该式子,我们可以预处理出$\varphi(i)$,$i\varphi(i)$,$i^2\varphi(i)$的前缀和,那么当n≤10^7时,可以实现O(1)求得答案

对于第三个子任务,$n≤10^{10}$,显然不可以预处理到$10^{10}$,求$\varphi(i)$,$i\varphi(i)$,$i^2\varphi(i)$的前缀和,我们可以通过杜教筛+预处理实现$O(n^{\frac{2}{3}})$的单次询问,可以通过第三个子任务。

杜教筛部分详见代码,在此不再展开。

完结撒花

 1 #include<bits/stdc++.h>
 2 #define L long long
 3 #define MOD 1000000007
 4 #define I2  500000004
 5 #define I6  166666668
 6 #define M 19890604
 7 using namespace std;
 8 int pri[M/10]={0},b[M]={0},use=0;
 9 int phi[M][3]={0};
10 
11 L get(L n,L op){
12     n%=MOD;
13     if(op==0) return n;
14     if(op==1) return ((1+n)*n/2)%MOD;
15     if(op==2) return n*(n+1)%MOD*(2*n+1)%MOD*I6%MOD;
16     n=(n*(n+1)/2)%MOD; return n*n%MOD;
17 }
18 map<L,L> mp[3];
19 L PHI(L n,L k){
20     if(n<M) return phi[n][k];
21     if(mp[k][n]) return mp[k][n];
22     L res=get(n,k+1);
23     for(L i=2,j;i<=n;i=j+1){
24         j=n/(n/i);
25         res=(res-(get(j,k)-get(i-1,k))*PHI(n/i,k))%MOD;
26     }
27     return mp[k][n]=res;
28 }
29 
30 L Main(){
31     L n; scanf("%lld",&n);
32     L p1=PHI(n,0),p2=PHI(n,1),p3=PHI(n,2);
33     L ans=(p1*2+p2*3+p3)%MOD*I2%MOD;
34     printf("%lld\n",(ans+1+MOD)%MOD);
35 }
36 
37 int main(){
38     phi[1][0]=phi[1][1]=phi[1][2]=1;
39     for(L i=2;i<M;i++){
40         if(b[i]==0) pri[++use]=i,phi[i][0]=i-1;
41         for(L j=1;j<=use&&i*pri[j]<M;j++){
42             b[i*pri[j]]=1;
43             if(i%pri[j]==0){phi[i*pri[j]][0]=phi[i][0]*pri[j]; break;}
44             phi[i*pri[j]][0]=phi[i][0]*(pri[j]-1);
45         }
46     }
47     for(L i=1;i<M;i++){
48         phi[i][2]=(phi[i-1][2]+1LL*i*i%MOD*phi[i][0])%MOD;
49         phi[i][1]=(phi[i-1][1]+i*phi[i][0])%MOD;
50         phi[i][0]=(phi[i-1][0]+phi[i][0])%MOD;
51     }
52     L cas; cin>>cas;
53     while(cas--) Main();
54 }

 

 

相关文章: