[洛谷 P2508] 圆上的整点

题目描述

求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。

输入输出格式

输入格式:

r

输出格式:

整点个数

输入输出样例

输入样例#1:
4
输出样例#1:
4

说明

n<=2000 000 000

 

暴力很好打,但是这1000%是数论题。不就是推推式子嘛。

由于圆这个东西很棒棒,我们只需要考虑某一象限内的情况就行了。为了方便解题,我们取第一象限作研究对象。

因为x^2+y^2=n^2,变换一下,y^2=n^2-x^2=(n-x)(n+x)。

设gcd(n-x,n+x)=d,a=(n-x)/d,b=(n+x)/d,则有gcd(a,b)=1。

又由于y^2=a*b*d^2,且都是整数,则a*b是完全平方数。又因gcd(a,b)=1,所以a,b都是完全平方数。

设a=u^2,b=v^2(显然gcd(u,v)=1),则:n-x=d*u^2,n+x=d*v^2,两式相加得2n=d*(u^2+v^2)(显然u<v)。

那么,我们获得了关于u和v的约数条件:

1.u^2+v^2=2n/d;

2.gcd(u,v)=1;

3.u<v;

那么,我们可以先通过O(sqrt(2n))的时间枚举d,然后通过sqrt(d)的时间枚举u,然后进行3个判断。时间复杂度约为O(2n^0.75)。

 

 1 #include<bits/stdc++.h>
 2 #define LL long long
 3 using namespace std;
 4 int n,ans;
 5 int gcd(int x,int y){return y?gcd(y,x%y):x;}
 6 void calc(LL oth){
 7     for (int u=1; u<=sqrt(oth); u++){
 8         int v=sqrt(oth-u*u);
 9         if (u>=v) continue;
10         if (u*u+v*v!=oth) continue;
11         if (gcd(u,v)!=1) continue;
12         ans++;
13     }
14 }
15 int main(){
16     scanf("%d",&n),ans=0;
17     for (int i=1; i<=sqrt((LL)n*2); i++)
18         if ((LL)n*2%i==0) calc(i),calc((LL)n*2/i);
19     printf("%d",ans*4+4);
20     return 0;
21 }
View Code

 

转载于:https://www.cnblogs.com/whc200305/p/7395920.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值