题目大意:给你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}igg(4+sum_{d=1}^{n}sum_{i=1}^{Q}sum_{j=1}^{Q}(di+1)(dj+1)igg)$其中$Q=lfloor frac{n}{d} floor $,下面同理
$=frac{1}{2}igg(4+sum_{d=1}^{n}mu(d)(Q^2+d(1+Q)Q^2+d^2(frac{(1+Q)Q}{2})^2)igg)$
不难发现,这个式子可以预处理出$mu(i)$的前缀和,然后通过根号分块的方法,实现单次$O(sqrt{n})$时间复杂度的询问操作。在前两个子任务中,时间复杂度为$O(Tsqrt{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 imes varphi(i)$。
那么原式为:
$=frac{1}{2}sum_{i=1}^{n}(i+1)(i+2)varphi(i)$
$=frac{1}{2}sum_{i=1}^{n}igg(2(i+1)varphi(i)+i(i+1)varphi(i) igg)$
$=frac{1}{2}igg( 2sum_{i=1}^{n}varphi(i)+3sum_{i=1}^{n}ivarphi(i)+sum_{i=1}^{n}i^2varphi(i) igg)$
该式子,我们可以预处理出$varphi(i)$,$ivarphi(i)$,$i^2varphi(i)$的前缀和,那么当n≤10^7时,可以实现O(1)求得答案
对于第三个子任务,$n≤10^{10}$,显然不可以预处理到$10^{10}$,求$varphi(i)$,$ivarphi(i)$,$i^2varphi(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 ",(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 }