n<=1e10,问1<=i<=n,1<=j<=n,gcd(i,j)的和%1e9+7。
QAQ自推的第一道,虽然很简单而且走了很多弯路而且推错了一次被ccz大爷调教,但还是挺感动的。。
其实在推数论之前可以先打个$\mu$和$\varphi $的表,推个两三步就验证一下,否则如果是大数论题,推错的后果是极其严重的。
$\sum_{i=1}^{n}\sum_{j=1}^{n}(i,j)$
$=\sum_{d=1}^{n}\sum_{i=1}^{n}\sum_{j=1}^{n}[(i,j)=d]$
严重错误!d不见了。上面这个式子最后等于1.
$\sum_{i=1}^{n}\sum_{j=1}^{n}(i,j)$
$=\sum_{d=1}^{n}d\sum_{i=1}^{n}\sum_{j=1}^{n}[(i,j)=d]$
闪一句:反演!
$=\sum_{d=1}^{n}d\sum_{d|t,t\leqslant n}\mu(\frac{t}{d})(\left \lfloor \frac{n}{t} \right \rfloor)^2$
闪一句:这里尝试$t=kd$,结果失败了。正确操作是把t放前面……
$=\sum_{t=1}^{n}(\left \lfloor \frac{n}{t} \right \rfloor)^2\sum_{d|t}d\mu(\frac{t}{d})$
$=\sum_{t=1}^{n}(\left \lfloor \frac{n}{t} \right \rfloor)^2\varphi(t)$
漂亮!把欧拉函数丢去杜教筛即可。
1 #include<string.h> 2 #include<stdlib.h> 3 #include<stdio.h> 4 #include<math.h> 5 //#include<assert.h> 6 #include<algorithm> 7 //#include<iostream> 8 //#include<bitset> 9 using namespace std; 10 11 #define LL long long 12 LL n,m; 13 const int mod=1e9+7; 14 #define maxn 5000011 15 int phi[maxn],sumphi[maxn],prime[maxn],lp; bool notprime[maxn]; 16 void pre(int n) 17 { 18 phi[1]=1; sumphi[1]=1; 19 for (int i=2;i<=n;i++) 20 { 21 if (!notprime[i]) prime[++lp]=i,phi[i]=i-1; 22 sumphi[i]=sumphi[i-1]+phi[i]; 23 sumphi[i]-=sumphi[i]>=mod?mod:0; 24 for (int j=1,tmp;j<=lp && 1ll*prime[j]*i<=n;j++) 25 { 26 notprime[tmp=prime[j]*i]=1; 27 if (i%prime[j]) phi[tmp]=phi[i]*(prime[j]-1); 28 else {phi[tmp]=phi[i]*prime[j]; break;} 29 } 30 } 31 } 32 33 struct Edge{LL to;int v,next;}; 34 #define maxh 1000007 35 struct Hash 36 { 37 int first[maxh],le; Edge edge[maxn]; 38 Hash() {le=2;} 39 void insert(LL y,int v) {int x=y%maxh; Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;} 40 int find(LL y) {int x=y%maxh; for (int i=first[x];i;i=edge[i].next) if (edge[i].to==y) return edge[i].v; return -1;} 41 }h; 42 43 int calc(LL n) 44 { 45 if (n<=m) return sumphi[n]; 46 int tmp=h.find(n); if (tmp!=-1) return tmp; 47 LL ans=1ll*n%mod*((n+1)%mod)%mod*((mod+1)>>1)%mod; 48 for (LL i=2,last;i<=n;i=last+1) 49 { 50 last=n/(n/i); 51 ans-=((last-i+1)%mod)*1ll*calc(n/i)%mod; 52 ans+=ans<0?mod:0; 53 } 54 h.insert(n,ans); 55 return ans; 56 } 57 58 int main() 59 { 60 scanf("%lld",&n); 61 m=pow(n,2.0/3); pre(m); 62 LL ans=0; 63 for (LL i=1,last;i<=n;i=last+1) 64 { 65 last=n/(n/i); 66 ans+=(calc(last)-calc(i-1))*1ll*((n/i)%mod)%mod*((n/i)%mod)%mod; 67 ans+=ans<0?mod:0,ans-=ans>=mod?mod:0; 68 } 69 printf("%lld\n",ans); 70 return 0; 71 }