题目概述
求
(i,j)∈P,1≤i≤n,1≤j≤m
(
P
是素数集)的
解题报告
按照BZOJ2301的方法,得出答案式子:
∑p∑d=1min{A′=⌊Ap⌋,B′=⌊Bp⌋}μ(d)⌊A′d⌋⌊B′d⌋
直接枚举素数显然会爆炸,所以再转化一下,令 T=pd ,那么:
∑T=1min{A,B}⌊AT⌋⌊BT⌋∑p|Tμ(Tp)
示例程序
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=1e7;
int te,n,m,mu[maxn+5],sum[maxn+5];
int p[maxn+5];bool pri[maxn+5];
void Make()
{
pri[1]=true;mu[1]=1;
for (int i=2;i<=maxn;i++)
{
if (!pri[i]) p[++p[0]]=i,mu[i]=-1;
for (int j=1,t;j<=p[0]&&(t=i*p[j])<=maxn;j++)
{
pri[t]=true;mu[t]=-mu[i];
if (!(i%p[j])) {mu[t]=0;continue;}
}
}
for (int j=1;j<=p[0];j++)
for (int i=1;i*p[j]<=maxn;i++)
sum[i*p[j]]+=mu[i];
for (int i=2;i<=maxn;i++) sum[i]+=sum[i-1];
}
inline LL Solve()
{
scanf("%d%d",&n,&m);LL ans=0;
for (int l=1,r;l<=n&&l<=m;l=r+1)
r=min(n/(n/l),m/(m/l)),ans+=(LL)(sum[r]-sum[l-1])*(n/l)*(m/l);
return ans;
}
int main()
{
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
for (Make(),scanf("%d",&te);te;te--) printf("%lld\n",Solve());
return 0;
}