BZOJ3994: [SDOI2015]约数个数和(莫比乌斯反演)

时间:2023-03-08 21:32:10

Description

 设d(x)为x的约数个数,给定N、M,求  BZOJ3994: [SDOI2015]约数个数和(莫比乌斯反演)

Input

输入文件包含多组测试数据。

第一行,一个整数T,表示测试数据的组数。
接下来的T行,每行两个整数N、M。

Output

T行,每行一个整数,表示你所求的答案。

Sample Input

2
7 4
5 6

Sample Output

110
121

解题思路:

有一个喜闻乐见的结论:

${\sum_{i=1}^{n}}{\sum_{j=1}^{m}}{d(i*j)]}={\sum_{i=1}^{n}}{\sum_{j=1}^{m}}[gcd(i,j)==1]{\left \lfloor \frac{N}{i} \right \rfloor}{\left \lfloor \frac{M}{j} \right \rfloor}$

剩下的大家都会了吧QAQ

代码:

 #include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int N=;
struct lnt{
std::map<unsigned int,long long>Arr;
long long arr[N];
bool has[N];
void Insert(unsigned int x,long long y)
{
if(x<N)
arr[x]=y,has[x]=true;
else
Arr[x]=y;
}
bool find(unsigned int x)
{
if(x<N)
return has[x];
else
return Arr.find(x)!=Arr.end();
}
long long val(unsigned int pos)
{
if(pos<N)
return arr[pos];
return Arr[pos];
}
};
unsigned int prime[N];
int phi[N];
int miu[N];
bool vis[N];
unsigned int cnt;
lnt Sum_phi;
lnt Sum_miu;
void gtp(void)
{
miu[]=phi[]=;
Sum_phi.Insert(,);
Sum_miu.Insert(,);
for(int i=;i<N;i++)
{
if(!vis[i])
{
prime[++cnt]=i;
miu[i]=-;
phi[i]=i-;
}
for(int j=;j<=cnt&&i*prime[j]<N;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==)
{
miu[i*prime[j]]=;
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
miu[i*prime[j]]=-miu[i];
phi[i*prime[j]]=phi[i]*(prime[j]-);
}
}
for(int i=;i<N;i++)
{
Sum_phi.Insert(i,Sum_phi.val(i-)+phi[i]);
Sum_miu.Insert(i,Sum_miu.val(i-)+miu[i]);
}
return ;
}
long long PHI_search(unsigned int pos)
{
if(Sum_phi.find(pos))
return Sum_phi.val(pos);
long long tmp=;
for(unsigned int i=,j;i<=pos;i=j+)
{
j=pos/(pos/i);
tmp+=PHI_search(pos/i)*(long long)(j-i+);
}
Sum_phi.Insert(pos,1ll*pos*(pos+)/-tmp);
return 1ll*pos*(pos+)/-tmp;
}
long long MIU_search(unsigned int pos)
{
if(Sum_miu.find(pos))
return Sum_miu.val(pos);
long long tmp=;
for(unsigned int i=,j;i<=pos;i=j+)
{
j=pos/(pos/i);
tmp+=(j-i+)*MIU_search(pos/i);
}
Sum_miu.Insert(pos,-tmp);
return -tmp;
}
int main()
{
gtp();
int T;
scanf("%d",&T);
while(T--)
{
int x;
scanf("%d",&x);
printf("%lld %lld\n",PHI_search(x),MIU_search(x));
}
return ;
}