Problem Description
定义一个函数 μ(x):如果 x 等于 k 个不同的质数的乘积,则 μ(x)=(−1)^k,否则(即 x 有大于 1 的平方因子) μ(x)=0
定义 lcm(a,b) 为 a,b 的最小公倍数,给定 n,m,你需要求:Input
第一行一个正整数 T(T≤10) 表示数据组数
接下来 T 行,每行两个正整数 n,m(1≤n,m≤106),表示一次询问Output
输出 T 行,每行一个整数表示该组数据的答案
Examples
Input
2
2 4
5 5Output
-2
-2
思路:
对于式子 进行化简,有:
将 ij 拆分,有:
由于莫比乌斯函数是积性函数,那么有:
将 k 提出,有:
考虑莫比乌斯函数 u(x) 的性质,已知:u(x) 为积性函数,当 时,有
即:
进行推广:当 时,有:
那么对于 k 来说,当满足: 时
有:
因此,有:
进行反演,有:
进行化简,有:
设 t=dk,进一步化简:
预处理 即可
Source Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL quickModPow(LL a,LL b,LL mod){ LL res=1; a=a%mod; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1;} return res; }
LL getInv(LL a,LL mod){ return quickModPow(a,mod-2,mod); }
const double EPS = 1E-10;
const int MOD = 20101009;
const int N = 1000000+5;
const int dx[] = {-1,1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;
int mu[N];
int prime[N];
bool bprime[N];
int cnt;
LL sum[N];
void getMu(int n){//线性筛求莫比乌斯函数
cnt=0;
mu[1]=1;//根据定义,μ(1)=1
memset(bprime,false,sizeof(bprime));
for(int i=2;i<=n;i++){//求2~n的莫比乌斯函数
if(!bprime[i]){
prime[++cnt]=i;//存储质数
mu[i]=-1;//i为质数时,μ(1)=-1
}
for(int j=1;j<=cnt&&i*prime[j]<=n;j++){//枚举i之前的素数个数
bprime[i*prime[j]]=true;//不是质数
if(i%prime[j])//i不是prime[j]的整数倍时,i*prime[j]就不会包含相同质因子
mu[i*prime[j]]=-mu[i];//mu[k]=mu[i]*mu[prime[j]],因为prime[j]是质数,mu值为-1
else{
mu[i*prime[j]]=0;
break;//留到后面再筛
}
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n/i;j++)
sum[i*j]+=mu[i]*mu[j];
}
int main(){
getMu(1000000);
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
if(n>m)
swap(n,m);
LL res=0;
for(int t=1;t<=n;t++){
LL sum1=0,sum2=0;
for(int i=1;i<=n/t;i++)
sum1+=mu[i*t];
for(int j=1;j<=m/t;j++)
sum2+=mu[j*t];
res+=sum1*sum2*sum[t];
}
printf("%lld\n",res);
}
return 0;
}