题目
定义d(x)表示x的约数个数,给定n,m,求:
思路
首先,新定义函数d没有特定的算法,因此需要对它做小小的处理。
易知,,
,
。
则令:
。
那么:
所以:
考虑枚举,此时考虑
,则a,b中就不会有相同的质因子。
所以:
带入原式得:
带入莫比乌斯反演结论:
到这里是不是很熟悉了?又可以用洛谷P2522 Problem b 的方法做了!详参上上篇题解:
到了这里,剩下的就交给整除分块了。
定义:
则可以对此函数进行如处理,那么答案就是:
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll z=1e6+9,N=5e4+9;
ll mu[z],p[z],np,xb[z],f[z];
bool isp[z];
ll T,n,m,ans;
void fastread()
{
ios::sync_with_stdio(0);
}
void getmu()
{
memset(isp,1,sizeof(isp));
isp[1]=0;
mu[1]=1;
for(ll i=2;i<=N;i++)
{
if(isp[i])
{
p[++np]=i;
mu[i]=-1;
}
for(ll j=1;j<=np&&i*p[j]<=N;j++)
{
ll x=i*p[j];
isp[x]=0;
if(i%p[j]!=0)mu[x]=-mu[i];
else
{
mu[x]=0;
break;
}
}
}
for(int i=1;i<=N;i++)
xb[i]=xb[i-1]+mu[i];
for(int i=1;i<=N;i++)
{
ll res=0;
for(int l=1,r;l<=i;l=r+1)
{
r=i/(i/l);
res+=(r-l+1)*(i/l);
}
f[i]=res;
}
}
ll cal(ll n,ll m)
{
ll res=0,rr=min(n,m);
for(int l=1,r;l<=rr;l=r+1)
{
r=min(n/(n/l),m/(m/l));
res+=(xb[r]-xb[l-1])*f[n/l]*f[m/l];
}
return res;
}
int main()
{
fastread();
cin>>T;
getmu();
while(T--)
{
cin>>n>>m;
ans=cal(n,m);
cout<<ans<<endl;
}
return 0;
}