题解:P2063 二平方和定理
littlez_meow · · 题解
我们把问题丢到复平面上,就是求
考虑在高斯整环
根据费马平方和定理,对于一个奇质数
也就是说,我们只需要把
设奇质数
根据二次剩余相关知识,
由于高斯整环是辗转相除环,这里的
那么我们已经可以把
先处理模
然后是模
最后是
时间复杂度为
代码
由于我自己写的 SQUFOF 假掉了,在这里粘了一个板子,就不放分解质因数的代码了。
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#define F(i,a,b) for(int i(a),i##i##end(b);i<=i##i##end;++i)
#define R(i,a,b) for(int i(a),i##i##end(b);i>=i##i##end;--i)
#define File(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
#define ll long long
#define int ll
#define fi first
#define se second
using namespace std;
__gnu_pbds::gp_hash_table<ll,int>e;
inline ll qpow(__int128 base,ll expo,const ll MOD){
ll res(1);
while(expo){
(expo&1)&&(res=res*base%MOD);
base=base*base%MOD,expo>>=1;
}
return res;
}
namespace Factorize{
inline void factorize(ll n,ll cnt=1){
}
}
struct Cpx{
__int128 a,b;//a+bi;
Cpx(const ll&x=0,const ll&y=0):a(x),b(y){}
Cpx operator+(const Cpx&x)const{return Cpx(a+x.a,b+x.b);}
Cpx operator-(const Cpx&x)const{return Cpx(a-x.a,b-x.b);}
Cpx operator*(const Cpx&x)const{return Cpx(a*x.a-b*x.b,a*x.b+b*x.a);}
Cpx operator/(const Cpx&x)const{
double qwq=x.a*x.a+x.b*x.b;
return Cpx(round((a*x.a+b*x.b)/qwq),round((b*x.a-a*x.b)/qwq));
}
Cpx operator%(const Cpx&x)const{
return *this-x*(*this/x);
}
Cpx operator^(ll ex)const{
Cpx res(1),b=*this;
while(ex) (ex&1)&&(res=res*b,1),b=b*b,ex>>=1;
return res;
}
bool operator==(const Cpx&x)const{return a==x.a&&b==x.b;}
__int128 abs()const{return a*a+b*b;}
};
Cpx gcd(const Cpx&x,const Cpx&y){
if(x.abs()<y.abs()) return gcd(y,x);
return y==Cpx()?x:gcd(y,x%y);
}
int cnt,ex[100];
ll pr[100];
Cpx coef[100];
mt19937 gen(114514);
vector<pair<ll,ll> >ans;
void dfs(int step,const Cpx&now){
if(step==cnt+1){
ll x=now.a,y=now.b;
if(x>=0&&y>=0) ans.emplace_back(x,y);
if(x<=0&&y<=0) ans.emplace_back(-x,-y);
if(y<=0&&x>=0) ans.emplace_back(-y,x);
if(y>=0&&x<=0) ans.emplace_back(y,-x);
return;
}
if((pr[step]&3)!=1) dfs(step+1,now*coef[step]);
else{
Cpx bar(coef[step].a,-coef[step].b),qwq=bar^ex[step];
F(i,0,ex[step]) dfs(step+1,now*qwq),qwq=qwq/bar*coef[step];
}
return;
}
inline void solve(){
cnt=0;
for(auto i:e){
pr[++cnt]=i.fi,ex[cnt]=i.se;
if(i.fi==2) coef[cnt]=Cpx(1,1)^i.se;
else if((i.fi&3)==1){
ll qwq;
while(1){
qwq=gen()%(i.fi-1)+1;
if(qpow(qwq,i.fi>>1,i.fi)==i.fi-1)break;
}
qwq=qpow(qwq,i.fi>>2,i.fi);
coef[cnt]=gcd(Cpx(i.fi),Cpx(qwq,1));
}else if(i.se&1) return cout<<"0\n",void();
else coef[cnt]=Cpx(qpow(i.fi,i.se>>1,1e18));
}
vector<pair<ll,ll> >().swap(ans);
dfs(1,Cpx(1,0));
sort(ans.begin(),ans.end());
cout<<ans.size()<<"\n";
for(auto i:ans) cout<<i.fi<<" "<<i.se<<"\n";
return;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
ll T,n;
for(cin>>T;T;--T){
e.clear();
cin>>n;
if(n<=1e10){
for(int i=2;i*i<=n;++i) if(n%i==0) while(n%i==0) n/=i,++e[i];
if(n!=1) ++e[n];
}else Factorize::factorize(n);
solve();
}
return 0;
}