思路
得到上面三部分后,可以预处理出来,时间复杂度O(nlogn),因为要筛。
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include<bits/stdc++.h> using namespace std; #define ll long long const int N = 1e6+10; int prime[N],cnt,mu[N]; int s3[N],s2[N],s1[N],n,m; bool vis[N]; void init(){ mu[1]=1; for(int i=2;i<N;i++){ if(!vis[i])prime[cnt++]=i,mu[i]=-1; for(int j=0;j<cnt&&i*prime[j]<N;j++){ vis[i*prime[j]]=true; if(i%prime[j]==0){ mu[i*prime[j]]=0; break; } mu[i*prime[j]]=-mu[i]; } } for(int i=1;i<N;i++) for(int j=i;j<N;j+=i) s3[j]+=mu[i]*mu[j/i]; } int main(){ int t; init(); scanf("%d",&t); while(t--){ scanf("%d %d",&n,&m); for(int i=1;i<=max(n,m);i++)s1[i]=s2[i]=0; if(n>m)swap(n,m); for(int i=1;i<=n;i++){ for(int j=i;j<=n;j+=i){ s1[i]+=mu[j]; } } for(int i=1;i<=m;i++){ for(int j=i;j<=m;j+=i){ s2[i]+=mu[j]; } } ll ans = 0; for(int i=1;i<=n;i++){ ans+=s1[i]*s2[i]*s3[i]; } printf("%lld\n",ans); } }
|