题意:
求gcd(x,y)的质因子的个数<=p的对数
思路:
Ans=∑(1<=i<=n, f(i)) (f(i)是gcd(x,y)==i的个数
=∑(1<=i<=n, ∑(i|d,mu(d/i)*F(d)) ) (F(i)是i|gcd(x,y)的个数
=∑(1<=i<=n, F(i) * ∑(d|i , mu(d)) )
由于有ok(i)的存在,我们要对预处理多加一个维度,就是素因子的个数
=∑(1<=i<=n, F(i) * ∑(d|i , mu(d) * ok(i/d)))
=∑(1<=i<=n, F(i) * ∑(d|i , mu(i/d) * ok(d)))
F(i)=(n/i)*(m/i)
所以对于每个F(i),mu的贡献就是 ∑(d|i,mu(d)) 这个可以预处理出来
然后就是比较简单的处理了
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long LL;
const int maxn = 500005;
const int inf=(1<<28)-1;
#define maxp 500005
int Sum[maxp][20];//Sum[i][j]代表mu对于F(i)的贡献在质因子个数<=j的基础上
int h[maxp],Num[maxp];//Num是质因子个数,h[i]是种类个数,-1代表mu[i]=-1
int GetMu(int x)
{
if(h[x]==-1) return 0;
else if(h[x]&1) return -1;
return 1;
}
void init()
{
Num[1]=0;h[1]=0;
for(int i=2;i<maxp;++i)
{
if(Num[i]) continue;
for(int j=i;j<maxp;j+=i)
{
int x=j,cnt=0;
while(x%i==0)
{
x/=i;cnt++;
}
Num[j]+=cnt;
if(cnt>1)
h[j]=-1;
else if(h[j]>=0)
h[j]++;
}
}
for(int i=1;i<maxp;++i)
{
for(int j=i;j<maxp;j+=i)
{
Sum[j][Num[j/i]]+=GetMu(i);//这里比较绕...多想想
}
}
for(int i=1;i<maxp;++i)
{
for(int j=1;j<20;++j)
Sum[i][j]+=Sum[i][j-1];
}
for(int i=1;i<maxp;++i)
{
for(int j=0;j<20;++j)
Sum[i][j]+=Sum[i-1][j];
}
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--)
{
int n,m,p;
scanf("%d%d%d",&n,&m,&p);
LL Ans=0;
if(p>=20)
Ans=(LL)n*m;
else
{
int t=min(n,m),last;
for(int i=1;i<=t;i=last+1)
{
last=min(n/(n/i),m/(m/i));
Ans+=(LL)(Sum[last][p]-Sum[i-1][p])*(n/i)*(m/i);
}
}
printf("%lld\n",Ans);
}
return 0;
}