a" />

### 【BZOJ3529】數表（SDOI2014）-莫比烏斯反演+樹狀數組

$ans=\underset{i=1}{\overset{n}{\sum }}\underset{j=1}{\overset{m}{\sum }}D\left(gcd\left(i,j\right)\right)$$ans=\sum_{i=1}^n\sum_{j=1}^mD(\gcd(i,j))$

$ans=\underset{d=1}{\overset{n}{\sum }}D\left(d\right)\underset{i=1}{\overset{n}{\sum }}\underset{j=1}{\overset{m}{\sum }}\left[gcd\left(i,j\right)=d\right]$$ans=\sum_{d=1}^nD(d)\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=d]$
$f\left(d\right)=\underset{i=1}{\overset{n}{\sum }}\underset{j=1}{\overset{m}{\sum }}\left[gcd\left(i,j\right)=d\right]$$f(d)=\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=d]$，我們發現這就是求 $gcd$$\gcd$等於 $d$$d$的數對個數（這簡直是句廢話）。

$f\left(d\right)=\underset{d|i}{\sum }\mu \left(\frac{i}{d}\right)F\left(i\right)=\underset{d|i}{\sum }\mu \left(\frac{i}{d}\right)⌊\frac{n}{i}⌋⌊\frac{m}{i}⌋$$f(d)=\sum_{d|i}\mu(\frac{i}{d})F(i)=\sum_{d|i}\mu(\frac{i}{d})\lfloor \frac{n}{i}\rfloor\lfloor \frac{m}{i}\rfloor$

$ans=\underset{d=1}{\overset{n}{\sum }}D\left(d\right)\underset{d|i}{\sum }\mu \left(\frac{i}{d}\right)⌊\frac{n}{i}⌋⌊\frac{m}{i}⌋$$ans=\sum_{d=1}^nD(d)\sum_{d|i}\mu(\frac{i}{d})\lfloor \frac{n}{i}\rfloor\lfloor \frac{m}{i}\rfloor$

$ans=\underset{i=1}{\overset{n}{\sum }}⌊\frac{n}{i}⌋⌊\frac{m}{i}⌋\underset{d|i}{\sum }D\left(d\right)\mu \left(\frac{i}{d}\right)$$ans=\sum_{i=1}^n\lfloor \frac{n}{i}\rfloor\lfloor \frac{m}{i}\rfloor\sum_{d|i}D(d)\mu(\frac{i}{d})$

#include <bits/stdc++.h>
using namespace std;
int T,p[100010];
int maxn,D[100010],mu[100010],s[100010],ans[20010];
int prime[100010];
bool vis[100010]={0};
struct query
{
int id,n,m,a;
}q[20010];

bool cmp(query a,query b)
{
return a.a<b.a;
}

bool cmpp(int a,int b)
{
return D[a]<D[b];
}

int lowbit(int x)
{
return x&(-x);
}

{
for(int i=x;i<=maxn;i+=lowbit(i))
s[i]+=c;
}

int sum(int x)
{
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=s[i];
return ans;
}

void init()
{
scanf("%d",&T);
maxn=0;
for(int i=1;i<=T;i++)
{
scanf("%lld%lld%lld",&q[i].n,&q[i].m,&q[i].a);
if (q[i].n>q[i].m) swap(q[i].n,q[i].m);
maxn=max(maxn,q[i].n);
q[i].id=i;
}
sort(q+1,q+T+1,cmp);

for(int i=1;i<=maxn;i++)
for(int j=1;i*j<=maxn;j++)
D[i*j]=D[i*j]+i;
for(int i=1;i<=maxn;i++)
p[i]=i;
sort(p+1,p+maxn+1,cmpp);
}

void calc_mu()
{
mu[1]=1;
prime[0]=0;
for(int i=2;i<=maxn;i++)
{
if (!vis[i])
{
prime[++prime[0]]=i;
mu[i]=-1;
}
for(int j=1;j<=prime[0]&&i*prime[j]<=maxn;j++)
{
vis[i*prime[j]]=1;
if (i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
}

int main()
{
init();
calc_mu();

int nowp=1;
for(int i=1;i<=T;i++)
{
while(D[p[nowp]]<=q[i].a)
{
for(int j=1;j*p[nowp]<=maxn;j++)
nowp++;
}
int n=q[i].n,m=q[i].m;
ans[q[i].id]=0;
for(int j=n;j>=1;j=max(n/(n/j+1),m/(m/j+1)))
{
int l=max(n/(n/j+1)+1,m/(m/j+1)+1),r=j;
ans[q[i].id]=ans[q[i].id]+(sum(r)-sum(l-1))*(n/j)*(m/j);
}
}

for(int i=1;i<=T;i++)
printf("%d\n",ans[i]&2147483647);

return 0;
}