Problem - 2841
参考:
求1~n中与m互质的数的个数(容斥原理)_Stormjing的博客-CSDN博客
hdu 2841 树围成矩阵,人在(0,0)点,最多可看到几棵树_maqinyao5566的博客-CSDN博客
题目大意:农民在(0,0)的位置看一个m*n的矩阵,与农民在同一条直线的树只能看见第一棵。
分析:在同一条直线上的树的坐标都可以表示为(x*k,y*k)(x,y,k>0)所以(x,y)(x y互质)就是第一棵,问题就转化为求xy互质(1<=x<=n,1<=y<=m),的个数
#include
using namespace std;
int n,x,y,ans;
int gcd(int x,int y)
{
if((x == 0)||(y == 0))
{
return x+y;
}
return gcd(y,x%y);
}
int main()
{
scanf("%d",&n);
for(int i = 0;i < n;i++)
{
long long ans = 0;
scanf("%d %d",&x,&y);
for(int i = 1;i <= x;i++)
{
for(int j = 1;j <= y;j++)
{
if(gcd(i,j) == 1)
{
ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}
TLE了
看这数据量,求互质的的地方需要优化
容斥 !
每一行
利用容斥原理,先求不互质的个数 ans,最后结果 n-ans。
先将 m 分解质因子。存到 p 数组里。
假如 m 有 2,3,5质因子,那么2, 3, 5的倍数与 m 都不互质,但是会有重复。用容斥原理算出正确的即可。
k / 2 + k / 3 + k / 5 - k / (2 * 3) - k / (3 * 5) - k / (2 * 5) + k / (2 * 3 * 5)
出现奇数次的加,出现偶数次的减。
#include
using namespace std;
int n,a,b,pf[10000],ct;
void p_f(int x)
{
for(int i = 2;i*i <= x;i++)
{
if(x%i == 0)
{
pf[ct++] = i;
while(x%i == 0)
{
x/=i;
}
}
}
if(x > 1)
{
pf[ct++] = x;
}
return;
}
long long rc(int a,int b)
{
ct = 0;
p_f(a);
long long ans = 0;
for (int i = 1; i < (1 << ct); i++){
long long tmp = 1, t = 0;
for(int j = 0; j < ct; j++){
if((1<