好多的树
时间限制:
3000
ms
|
内存限制:
65535
KB
难度:
5
-
描述
-
在那遥远的地方有一片神奇的森林,它的神奇之处是:森林中的每棵树都长在一对整数确定的坐标上。有一个小红人站在(0,0)的位置上,放眼望去,看到很多的树,眼前的树是那么的多,以至于它一直数不清。那么就来写个程序帮它数数吧!
-
-
输入
-
第一行一个整数n,代表测试数据组数。
接下来有n(n<=20)行数,每行数有两个整数i,j代表任何的(x,y)(0<=100000,0<=100000)的整数坐标上都有一棵树。
小红人始终是站在(0,0) 点上看树的。
输出
- 输出小红人看到的树的个数。每个结果占一行。 样例输入
-
1 7 4
样例输出
-
20
来源
- hduoj
-
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CLR(a,v) memset(a,v,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair 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 ;
} -
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()
{
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;
}
-
第一行一个整数n,代表测试数据组数。