题目大意:你在(0,0)处,给你一片地n*m,从(1,1)开始,问你能看见多少棵树。
思路:这道题跟一道校赛题非常像,当时写得死去活来,但是最后用欧拉函数写出来了。现在一看倒是非常地简单,就是一道互斥原理的题。因为你站在(0,0)处,所以每一棵树跟你连线都可以直接构称斜率。斜率相同的树显然我们只能看见第一颗,那么就是每一个数求他互质的数就完了。从1到n中的每一个数,对于m求互质的数。
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn = 1e5+10;
int prime[maxn];
int len;
void getprime(int n)
{
len = 0;
for(int i =2;i*i<=n;i++)
{
if(n %i == 0)
prime[len++] = i;
while(n%i == 0) n/=i;
}
if(n>1)
prime[len++] = n;
}
int solve(int n, int y)
{
getprime(n);
long long ans = y;
for(int i =1;i<(1<<len);i++)
{
int cnt = 0;
int temp = 1;
for(int j = 0;j<len;j++)
{
if(i&(1<<j))
{
cnt++;
temp *= prime[j];
}
}
if(cnt %2== 1)
ans -= y/temp;
else
ans += y/temp;
}
return ans;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int x,y;
scanf("%d%d", &x, &y);
if(x>y)swap(x,y);
long long ans = 0;
for(int i = 1;i<=x;i++)
{
ans += solve(i, y);
}
printf("%lld\n", ans);
}
return 0;
}