Description
设d(x)为x的约数个数,给定1<=T<=50000 组1<=N, M<=50000 ,求
有一个公式$$d(ij)=sum_{x|i}sum_{y|j}[gcd(i,j)=1]$$
先简单证明一下
如果(p_1^{k_1}|iwedge p_1^{k_2}|j) ,那么对于(ij)的一个因子(p_1^{k_3}) ,如果(k_3leq k_1)我们就假设(p_1^{k_3})全部来自于(i),不然就是(k_1)来自于(i),剩余部分(k_3-k_1)来自(k_2)这样的话,如果(p_1^{k_3}|x)就表示含有(p_1^{k_3})的那个因数,如果(p_1^{k_3}|y)就表示含有(p_1^{k_1+k_3}) 的那个因数。就可以表示出全部因数!这时(gcd(i,j) eq 1)的表示是没有意义的!
然后就可以开始欢乐的画柿子了
[ans=sum_{i=1}^{n}sum_{j=1}^msum_{x|i}sum_{y|j}[gcd(x,y)=1]
]
[=sum_x^nsum_y^mlfloorfrac n x
floorlfloorfrac m y
floorsum_{k|xwedge k|y}mu(k)
]
[=sum_{k=1}^{min(n,m)}mu (k)sum_{x=1}^{lfloorfrac n x
floor}sum_{y=1}^{lfloorfrac m y
floor}lfloorfrac n {xk}
floorlfloorfrac m {yk}
floor
]
[=sum_{k=1}^{min(n,m)}mu (k)sum_{x=1}^{lfloorfrac n x
floor}sum_{y=1}^{lfloorfrac m y
floor}lfloorfrac {lfloorfrac n k
floor} x
floorlfloorfrac {lfloorfrac m k
floor} y
floor
]
恩...
预处理一个函数(g(x)=sum_{i=1}^x lfloor frac x i floor)
后面那一块$$sum_{x=1}^{lfloorfrac n x floor}sum_{y=1}^{lfloorfrac m y floor}lfloorfrac {lfloorfrac n k floor} x floorlfloorfrac {lfloorfrac m k floor} y floor$$
就可以在这个基础上整除分块了啊,整个的时间复杂度(O(Tsqrt n))
#include<iostream>
#include<cstdio>
#include<cstring>
#define M 50001
#define LL long long
using namespace std;
int m,n,k,cnt,p[M],b[M],x,y;
LL mu[M],g[M];
void Mu()
{
mu[1]=1;
for(int i=2;i<M;i++)
{
if(!b[i]) {p[++cnt]=i, mu[i]=-1;}
for(int j=1;j<=cnt && p[j]*i<M;j++)
{
b[i*p[j]]=1; if(i%p[j]==0) break;
mu[i*p[j]]=-mu[i];
}
}
for(int i=2;i<M;i++) mu[i]+=mu[i-1];
}
int main()
{
Mu();
for(int i=1;i<M;i++)
for(int l=1,r;l<=i;l=r+1)
{
r=i/(i/l);
g[i]+=(r-l+1ll)*((LL)i/l);
}
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y); LL ans=0; if(x>y) swap(x,y);
for(int l=1,r;l<=x;l=r+1)
{
r=min(x/(x/l),y/(y/l));
ans+=(g[x/l]*g[y/l])*(mu[r]-mu[l-1]);
}
printf("%lld
",ans);
}
}