P2508 [HAOI2008]圓上的整點
題意:求半徑為\(r\)的圓上有多少個整點,即求\(x^2+y^2=r^2\)有多少組整數解。
我們考慮把\(r^2=x^2+y^2\)變形,得到\(r^2=x^2-(-y^2)=(x+yi)(x-yi)\)。
所以我們就需要考慮通過分解\(r^2\)可以得到多少組不同的\((x+yi)(x-yi)\)。
我們考慮如果有若干對共軛複數分別放在兩邊,最後得到的也是一對共軛複數,相乘就可以得到整數,我們希望這個整數是\(r\)。
那麼就考慮如何求並分配這若干對共軛複數。
費馬平方和定理:奇素數 p 可以表示為兩個正整數的平方和,當且僅當 p 是 4 k+1 型的。並且在不考慮兩個正整數順序的情況下,這個表示方法唯一。
引入一個概念:高斯素數,即3,7這樣形似4 n+3的素數,他們一定不能被分成\((x+yi)(x-yi)\)的形式。
否則,如果是形似4 n+1的素數,一定能被分成\((x+yi)(x-yi)\)的形式。
那麼是否還忽略了某個素數呢?沒錯,2要特殊考慮,雖然它能被分成\(1^2+1^2=(1+i)(1-i)\),但特殊的是它所分解出的這兩個高斯整數的夾角還剛好是90度,這個要在計算答案的時候特殊考慮一下。
根據整數的惟一分解定理,我們可以讓\(r=p_1^{r_1}*p_2^{r_2}*...*p_k^{r_k}\)。考慮每個質因子對答案的影響。
如果這個因子不是高斯素數,也就是它能被分解成\((x+yi)(x-yi)\)
如果這個因子是高斯因數,也就是它不能被分解成\((x+yi)(x-yi)\),但是我們又一定要最後得到的等式兩邊共軛,所以只有當它的冪次\(m\)是偶數的時候,才能平均的分配到兩邊,否則就無解。
當然,我們也可以把\((x+yi),(x-yi)\)乘上\(-1,i,-i\)得到新的分解\((-x-yi),(-x+yi),(-y+xi),(y+xi),(y-xi),(-y-xi)\)
等等,是不是忘了什麼?素數2還沒有在我們討論的範圍中。它可以分為\((1+i)(1-i)\),我們還是選擇放到兩邊,但是我們對它分解得到的兩個共軛複數來乘上\(-1,i,-i\),得到的分解是\((-1-i),(-1+i),(-1+i),(1+i),(1-i),(-1-i)\),我們可以發現這樣會得到重複的複數。
不妨在幾何中理解一下。
上面的乘上\(-1,i,-i\)其實就是把\((a+bi),(a-bi)\)兩個點旋轉起來,但是當這兩個點的夾角是90度的時候,這旋轉不能得到新的解,所以2對答案沒有影響。
所以最後的答案就是,將\(r^2\)進行質因數分解,一個高斯素數\(p^m\)若m是奇數,答案為0,否則不會對答案造成影響,一個非高斯素數\(p^m\)對答案的貢獻是\(m+1\),2忽略不計。
但是由於\(r^2\)裡的每一個質數的指數一定是偶數,所以答案不會為0。其他的就沒有問題了。
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int ans(int n){
int res=1;
for(int i=2;i*i<=n;i++){
if(n%i==0){
int cnt=0;
while(n%i==0)n/=i,cnt++;
if(i%4==1)res*=(cnt<<1|1);
}
}
if(n!=1&&n%4==1)res*=(2+1);
return res<<2;
}
signed main(){
int n;
cin>>n;
cout<<ans(n)<<endl;
return 0;
}