[SDOI2015]约数个数和

题目大意:
  $q(qleq50000)$组询问,对于给定的$n,m(n,mleq50000)$,求$displaystylesum_{i=1}^nsum_{j=1}^m au(ij)$。

思路:
  $displaystyle au(ij)=sum_{x|i}sum_{y|j}[gcd(x,y)==1]$。

$$
egin{align*}
原式&=sum_{i=1}^nsum_{j=1}^msum_{x|i}sum_{y|j}[gcd(x,y)==1]\
&=sum_{i=1}^nsum_{j=1}^msum_{x|i}sum_{y|j}sum_{d|gcd(x,y)}mu(d)\
&=sum_{i=1}^nsum_{j=1}^msum_{d|gcd(i,j)}mu(d) au(frac id) au(frac jd)\
&=sum_{d=1}^{min(n,m)}sum_{i=1}^{lfloorfrac nd floor} au(i)sum_{j=1}^{lfloorfrac md floor} au(j)
end{align*}
$$
  其中$sum au(i)$可以线性筛预处理,$d$可以数论分块枚举,单次询问复杂度$O(sqrt n)$。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<algorithm>
 4 typedef long long int64;
 5 inline int getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int N=50001,M=5134;
13 bool vis[N];
14 int p[M],mu[N],tau[N],cnt[N],sum_mu[N],sum_tau[N];
15 inline void sieve() {
16     mu[1]=tau[1]=sum_mu[1]=sum_tau[1]=1;
17     for(register int i=2;i<N;i++) {
18         if(!vis[i]) {
19             p[++p[0]]=i;
20             mu[i]=-1;
21             cnt[i]=1;
22             tau[i]=2;
23         }
24         for(register int j=1;j<=p[0]&&i*p[j]<N;j++) {
25             vis[i*p[j]]=true;
26             if(i%p[j]==0) {
27                 mu[i*p[j]]=0;
28                 cnt[i*p[j]]=cnt[i]+1;
29                 tau[i*p[j]]=tau[i]/cnt[i*p[j]]*(cnt[i*p[j]]+1);
30                 break;
31             }
32             mu[i*p[j]]=-mu[i];
33             cnt[i*p[j]]=1;
34             tau[i*p[j]]=tau[i]*2;
35         }
36         sum_mu[i]=sum_mu[i-1]+mu[i];
37         sum_tau[i]=sum_tau[i-1]+tau[i];
38     }
39 }
40 int main() {
41     sieve();
42     for(register int T=getint();T;T--) {
43         const int n=getint(),m=getint(),lim=std::min(n,m);
44         int64 ans=0;
45         for(register int l=1,r;l<=lim;l=r+1) {
46             r=std::min(n/(n/l),m/(m/l));
47             ans+=(int64)(sum_mu[r]-sum_mu[l-1])*sum_tau[n/l]*sum_tau[m/l];
48         }
49         printf("%lld
",ans);
50     }
51     return 0;
52 }
原文地址:https://www.cnblogs.com/skylee03/p/8477009.html