题意:求n内本原毕达哥拉斯三元组的组数,以及n内没有被毕达哥拉斯数涉及到数的个数。
名词解释:
毕达哥拉斯三元组:又名勾股定理
本原的毕达哥拉斯三元组:
指如果一个毕达哥拉斯三元组x,y,z 满足GCD(x,y,z)=1,那么这个毕达哥拉斯三元组称为本原的
定理: 正整数x,y,z构成一个本原毕达哥拉斯三元组且y为偶数,当且仅当存在互素的正整数m,n(m>n),其中m为奇数n为偶数,或者m为偶数n为奇数 并且满足 x=m*m-n*n, y=2*m*n, z=m*m+n*n 。
解题思路:利用上式求出所给范围内的本原毕达哥拉斯三元组数,只需枚举m,n即可,然后将三元组乘以i(保证i*z<=n),就可以求出所有的毕达哥拉斯三元组。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
#define N 1000005
int flag[N];
int ans1=0;
int ans2=0;
int gcd(int x,int y)
{
return y==0?x:gcd(y,x%y);
}
void solve(int xx)
{
ans1=0;
ans2=0;
memset(flag,0,sizeof(flag));
int temp=(int)sqrt(xx*1.0);
for(int i=1;i<=temp;i++)
{
for(int j=i+1;j<=temp;j++)
{
if(i*i+j*j>xx) break;
if((i%2)!=(j%2))
{
if(gcd(i,j)==1)
{
int x=j*j-i*i;
int y=2*i*j;
int z=i*i+j*j;
ans1++;
int k;
for(k=1;;k++)
{
if(k*z>xx) break;
flag[k*x]=1;
flag[k*y]=1;
flag[k*z]=1;
}
}
}
}
}
for(int i=1;i<=xx;i++)
{
if(!flag[i]) ans2++;
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
solve(n);
printf("%d %d\n",ans1,ans2);
}
return 0;
}
PS:其实纯暴力也是可以解决的,,,