hdu 2841 Visible Trees(可见的树)

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<

你可能感兴趣的:(c++)