BZOJ 1041 圓上的整點 數論
阿新 • • 發佈:2019-01-26
題意:給出R,問半徑為R的圓上有多少個整數點? R<=2e9.
x^2+y^2=r^2. -> (r+x)(r-x)=y^2 . 令d=gcd(r+x,r-x).m=(r+x)/d,n=(r-x)/d.
則y^2= d^2*m*n . 因為gcd(m,n)=1 所以m,n都為完全平方數.(m,n素因子分解後的冪都為偶數.)
那麼讓m=u^2,n=v^2. 得:r+x=d*u^2,r-x=d*v^2. 相加後得: 2r=d(u^2+v^2).
d為2r的約束. Sqrt(2r)內列舉d 然後在Sqrt(2r/d)內列舉u即可.得到(u,v,d)就能確定一組(x,y) .注意gcd(u,v)=1.
先將R做素因子分解.R^2=p1^q1 * ...pk^qk.
若p mod 4 = 1 那麼它可以拆成一組共軛高斯素數相乘.
若p mod 4 = 3 那麼這個p不能被拆分.
每個p拆分成(a+bi)*(a-bi) 分成左右兩列.分別放互為共軛的複數.
最後兩列結果分別為(A+Bi)(A-Bi). A^2+B^2=R^2.
x^2+y^2=r^2. -> (r+x)(r-x)=y^2 . 令d=gcd(r+x,r-x).m=(r+x)/d,n=(r-x)/d.
則y^2= d^2*m*n . 因為gcd(m,n)=1 所以m,n都為完全平方數.(m,n素因子分解後的冪都為偶數.)
那麼讓m=u^2,n=v^2. 得:r+x=d*u^2,r-x=d*v^2. 相加後得: 2r=d(u^2+v^2).
d為2r的約束. Sqrt(2r)內列舉d 然後在Sqrt(2r/d)內列舉u即可.得到(u,v,d)就能確定一組(x,y) .注意gcd(u,v)=1.
因為上面算的只是第一象限內的點.答案乘4後+4個座標軸上的點即可.
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+5; ll R; ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} int main() { cin>>R; R*=2; ll res=0; for(ll i=1;i*i<=R;i++) { if(R%i) continue; ll t=R/i; for(ll u=1;u*u<=t;u++) { ll v=sqrt(t-u*u); if(v<=u) break; if(v*v+u*u!=t) continue; if(gcd(u,v)==1) res++; } if(i*i==R) break; t=i; for(ll u=1;u*u<=t;u++) { ll v=sqrt(t-u*u); if(v<=u) break; if(v*v+u*u!=t) continue; if(gcd(u,v)==1) res++; } } res*=4; res+=4; cout<<res<<'\n'; return 0; }
mark
圓上的整數點(a,b)滿足 a^2+b^2=R^2.
等價於在複平面上有多少個z=a+bi 滿足(a+bi)*(a-bi)=a^2+b^2 =R^2先將R做素因子分解.R^2=p1^q1 * ...pk^qk.
若p mod 4 = 1 那麼它可以拆成一組共軛高斯素數相乘.
若p mod 4 = 3 那麼這個p不能被拆分.
每個p拆分成(a+bi)*(a-bi) 分成左右兩列.分別放互為共軛的複數.
最後兩列結果分別為(A+Bi)(A-Bi). A^2+B^2=R^2.
總共選法為4*(q1+1)*...(qk+1). qi都為mod4==1的素數. 4為複數乘上1,-1,i,-i.