特殊不定方程的应用,跟普通的不定方程一样,还是要依靠扩展欧几里德来解决,,可能方程有点偏,
题意,给一个正数N,求小于等于正数N的树中,本原的毕达哥斯拉三元组的个数 和 毕达哥斯拉三元组不涉及N以内的数的个数
解析前小广告!总是做算法,不如来个陶冶情操的文章一篇: http://www.sanwen.net/subject/3628849/
解析:
本原毕达哥斯拉三元组 :
x = m^2 - n^2
y = 2 * m * n;
i * z = m^2 + n^2
其中m >n,且n,m两个数的奇偶性必须不同;即m为奇数 n为偶数,或者m为偶数 n为奇数
如此只需要对n,m,进行枚举即可,然后讲三元组乘以i 并且要保证 i*z在n范围内,这样就能够够求出所有的毕达哥斯拉三元组了、
#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#define ll long long
#define eps 1e-8
#define inf 0xfffffff
//const ll INF = 1ll<<61;
using namespace std;
//vector<pair<int,int> > G;
//typedef pair<int,int > P;
//vector<pair<int,int> > ::iterator iter;
//
//map<ll,int >mp;
//map<ll,int >::iterator p;
bool vis[1000000 + 5];
int ans1,ans2;
void init() {
memset(vis,false,sizeof(vis));
ans1 = ans2 = 0;
}
ll exgcd(ll a, ll b, ll &x0, ll &y0) {
if(!b) {
x0 = 1; y0 = 0;
return a;
}
ll r = exgcd(b, a%b, y0, x0);
y0 -= a/b*x0;
return r;
}
void cal(int tmpn) {
int tmp,i,x,y,z;
tmp = sqrt(tmpn * 1.000);
for(int n=1;n<=tmp;n++) {
for(int m=n+1;m<=tmp;m++) {
if(m * m + n * n > tmpn)break;//为了看方程方便 所以设变量为 n,m
if(n%2 != m%2) {
ll x0,y0;
if(exgcd(m,n,x0,y0) == 1) {
x = m * m - n * n;
y = 2 * m * n;
z = m * m + n * n;
ans1++;
for(int i=1;;i++) {
if(i * z > tmpn)break;
vis[i * x] = true;
vis[i * y] = true;
vis[i * z] = true;
}
}
}
}
}
}
int main() {
int n;
while(scanf("%d",&n) == 1) {
init();
cal(n);
for(int i=1;i<=n;i++)
if(!vis[i])
ans2++;
printf("%d %d\n",ans1,ans2);
}
return EXIT_SUCCESS;
}