给定一个半径R<2000000000;求以(0,0)为圆心的圆上有多少个整数点:
在这里直接给出代码:
解析参考:这篇博客
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
using namespace std;
long long R,ans=0;
long long gcd(long long x,long long y){return x%y==0 ? y : gcd(y,x%y);}
bool check(long long y,double x)
{
if(x==floor(x))//判断整点
{
long long x1=(long long)floor(x);
if(gcd(x1*x1,y*y)==1 && x1*x1!=y*y)//gcd(A,B)=1并且A!=B
return true;
}
return false;
}
int main()
{
//freopen("input.in","r",stdin);
//freopen("output.out","w",stdout);
scanf("%lld",&R);
for(long long d=1;d<=(long long)sqrt(2*R);d++)
{
if((2*R)%d==0)
{
for(long long a=1;a<=(long long)sqrt(2*R/(2*d));a++)//2*a^2<2*r/d
{
double b=sqrt(((2*R)/d)-a*a);
if(check(a,b))
ans++;
}
if(d!=(2*R)/d)
{
for(long long a=1;a<=(long long)sqrt(d/2);a++)//2*a^2<d
{
double b=sqrt(d-a*a);
if(check(a,b))
ans++;
}
}
}
}
printf("%lld\n",ans*4+4);
//system("pause");
return 0;
}
例二:
题意:
ABC三点,其中A是坐标原点,|AB|=a, |AC|=b,|BC|=c,求B、C在网格的可能坐标(横纵坐标都是整数),按字典序从小到大输出。
分析:
问题转化为圆1:x2+y2=a2 , ,圆2:x2+y2=b2 ,在两圆在各取一点(横纵坐标都为整数,下同),使得这两点之间的距离是c。只要能求出圆上的所有整点,题目基本上就解决了。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node{
ll x, y;
friend bool operator < (node a, node b)
{
return a.x == b.x ? a.y < b.y : a.x < b.x;
}
};
struct Line{
ll x1, y1, x2, y2;
};
vector<Line> ans;
vector<node> f, s;
ll r1, r2, c;
ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a%b);
}
bool check(ll a, double b)
{
ll bb = b;
if(bb == b)//b是整数
{
if(gcd(a*a, bb*bb) == 1 && a*a != bb*bb)
return true;
}
return false;
}
void getPoints(ll r, vector<node> &s)
{
for(ll d = 1; d <= (ll)sqrt(2*r); d++)//只枚举一半,d<=m
{
if((2*r)%d == 0)
{
ll m = (2*r) / d;// d*m=2*r
for(ll a = 1; a <= (ll)sqrt(m/2.0); a++)
{
double b = sqrt(m-a*a);
if(check(a, b))
{
ll y = r - a*a*d;
ll x = (ll)sqrt(r*r - y*y);
s.push_back({x, y});
s.push_back({x, -y});
s.push_back({-x, y});
s.push_back({-x, -y});
}
}
if(d != (2*r)/d)//m和d不等大,否则就重复了
{
m = d;//处理d>m的部分,此时d和m值互换,d = 2*r / d;
ll dd = 2*r / d;
for(ll a = 1; a <= (ll)sqrt(m/2.0); a++)
{
double b = sqrt(m-a*a);
if(check(a, b))
{
ll y = r - a*a*dd;
ll x = (ll)sqrt(r*r - y*y);
s.push_back({x, y});
s.push_back({x, -y});
s.push_back({-x, y});
s.push_back({-x, -y});
}
}
}
}
}
}
int main()
{
//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
int t;
scanf("%d", &t);
while(t--)
{
f.clear();s.clear();ans.clear();
scanf("%lld %lld %lld", &r1, &r2, &c);
f.push_back({0,r1});f.push_back({0,-r1});f.push_back({r1,0});f.push_back({-r1,0});
s.push_back({0,r2});s.push_back({0,-r2});s.push_back({r2,0});s.push_back({-r2,0});
getPoints(r1, f);
getPoints(r2, s);
sort(f.begin(), f.end());
sort(s.begin(), s.end());
for(int i = 0; i < f.size(); i++)
{
for(int j = 0; j < s.size(); j++)
{
ll dis = (f[i].x - s[j].x)*(f[i].x-s[j].x) + (f[i].y-s[j].y)*(f[i].y-s[j].y);
if(dis == c*c)
ans.push_back({f[i].x,f[i].y,s[j].x,s[j].y});
}
}
printf("%d\n",ans.size());
for(int i = 0; i < ans.size(); i++)
printf("%lld %lld %lld %lld\n", ans[i].x1, ans[i].y1, ans[i].x2, ans[i].y2);
}
return 0;
}