/*
NYOJ471 好多的树 -- 容斥原理
求互质数对(0<i<n , 0<j<m)的个数
打表 f[i]表示有几个素因子,如果存在相同的则为-1(素因子一次不能多除)
f[1]=0
f[2]=1
f[3]=1
f[4]=-1
f[5]=1
f[6]=2
f[7]=1
f[8]=-1
f[9]=-1
f[10]=2
然后就是解
if(f[i]>=0)
ans += (f[i]&1) ? (-((ll)n/i)*((ll)m/i)) : (((ll)n/i)*((ll)m/i));
*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <functional>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <ctime>
#include <queue>
#include <cmath>
#include <set>
#define CLR(a,v) memset(a,v,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const double PI = acos(-1.0);
const int N = 1e5+10;
ll gcd (int a,int b){
return b ? gcd(b, a%b) : a ;
}
void TestRand(){
srand((unsigned int)time(NULL));
int g = 0 , i = 0;
for( i = 0 ; i < 500000 ; i++)
if(gcd( rand()+1,rand()+1 ) == 1){
g++;
}
printf("%lf %lf\n",g*1.0/i,6.0/(PI*PI));
}
int prime[N];
bool p[N];
int GetPrime(){
int cnt = 0;
for(int i = 2 ; i < N ; i++){
if( !p[i] ){
prime[cnt++] = i;
for(int j = i+i ; j < N ; j+=i){
if(!p[j])
p[j]=true;
}
}
}
return cnt;
}
int f[N]; // f[i] i的素因子个数
void Init(int PrimeCnt){
f[1]=0;
for(int i = 2 ; i < N; i++){
if(!p[i]){f[i]=1;continue;} // 如果是素数
int a = i;
for(int j = 0 ; j < PrimeCnt ; j++){
if(a % prime[j] == 0){
f[i]++;
a /= prime[j];
}
if(a % prime[j] == 0){
f[i] = -1;
a /= prime[j];
}
if(a < prime[j] || f[i]==-1) break;
}
}
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int PrimeCnt = GetPrime();
Init(PrimeCnt);
int T;
scanf("%d",&T);
while(T--){
int m,n;
scanf("%d%d",&m, &n);
int bound = min(m,n);
ll ans = 0;
for(int i = 1 ; i <= bound ; i++){
if(f[i]>=0){
ans += (f[i]&1) ? (-((ll)n/i)*((ll)m/i)) : (((ll)n/i)*((ll)m/i));
}
}
printf("%lld\n",ans);
}
return 0;
}
【解题报告】NYOJ471 好多的树 -- 容斥原理
最新推荐文章于 2020-03-28 21:15:28 发布