51nod 1171 两个数的平方和

版权声明:原来这里可以拿来卖萌ヽ(・∀・)ノ https://blog.csdn.net/u012345506/article/details/82889541

先考虑素数 p p 的平方和:

p = 2 p=2 时,显然只有唯一解 2 = 1 2 + 1 2 2=1^2+1^2
p 3 m o d    4 p\equiv 3 \mod 4 时,显然无解,因为任何数的平方模 4 4 只可能为 0 , 1 0,1
p 1 m o d    4 p\equiv 1\mod 4 时,由于此时 1 -1 必然是 p p 的二次剩余,设 x 2 1 m o d    p x^2\equiv -1\mod p ,有:
x 2 + 1 0 m o d    p ( α + i ) ( α i ) 0 m o d    p x^2+1\equiv 0\mod p\\ (\alpha+i)(\alpha-i)\equiv 0 \mod p
注意到 p ( a + b i ) = p a + p b i p(a+bi)=pa+pbi ,而 α + 1 \alpha +1 α 1 \alpha -1 显然不满足这种形式,所以 p p 的因子同时存在于他们之中,即 p p 不是高斯素数。则:
p = α β α , β 1 p 2 = α 2 β 2 p=\alpha\beta|\alpha,\beta\neq 1\\ p^2=\alpha^2\beta^2
因为 p p 是素数,所以:
α 2 = β 2 = p a + b i = c + d i = p a 2 + b 2 = c 2 + d 2 = p \alpha^2=\beta^2=p\\ |a+bi|=|c+di|=p\\ a^2+b^2=c^2+d^2=p
故此时 p p 能够成为两个数的平方和,同时这一对数唯一且共轭,否则将与唯一分解定理相悖。

接着考虑合数的平方和:

我们直接将 n n 写成高斯素数的分解形式,那么:
p = 2 p=2 时, p = ( 1 + i ) ( 1 i ) = i ( 1 + i ) 2 = ( 1 + i ) 2 p=(1+i)(1-i)=i(1+i)^2=(1+i)^2
p 3 m o d    4 p\equiv 3 \mod 4 时,用之前的分析方式可以发现其一定是高斯素数,即 p = ( p + 0 i ) = p p=(p+0i)=p
p 1 m o d    4 p\equiv 1\mod 4 时, p = α α p=\alpha\overline{\alpha}
即:
n = ( 1 + i ) 2 A k = 0 B p k d k j = 0 C ( a j + b j i ) q j ( a j b j i ) q j n=(1+i)^{2A}\prod_{k=0}^Bp_k^{d_k}\prod_{j=0}^C(a_j+b_ji)^{q_j}(a_j-b_ji)^{q_j}
注意到如果 a 2 + b 2 = n a^2+b^2=n ,那么 n = ( a + b i ) ( a b i ) n=(a+bi)(a-bi) ,即 n n 的一对共轭因数。那么我们将其中一个因数写出来:
α = ( 1 + i ) a k = 0 B p k b k j = 0 C ( a j + b j i ) c j ( a j b j i ) d j a 2 A , b k d k , c j , d j q j \alpha =(1+i)^{a}\prod_{k=0}^Bp_k^{b_k}\prod_{j=0}^C(a_j+b_ji)^{c_j}(a_j-b_ji)^{d_j}\\ a\le 2A,b_k\le d_k,c_j,d_j\le q_j
接着将他的共轭写出来( 1 i = i ( 1 + i ) = 1 + i 1-i=i(1+i)=1+i ):
α = ( 1 + i ) a k = 0 B p k b k j = 0 C ( a j + b j i ) d j ( a j b j i ) c j \overline \alpha=(1+i)^{a}\prod_{k=0}^Bp_k^{b_k}\prod_{j=0}^C(a_j+b_ji)^{d_j}(a_j-b_ji)^{c_j}
可以发现,为了满足条件, a a b k b_k 已经确定了,他们必须为 A A d k 2 \frac{d_k} 2 ,所以 d k d_k ,即模 4 4 3 3 的素数的幂必须为偶数。剩下的可选项只有 d j , c j d_j,c_j ,注意到他们必须满足 c j + d j = q j c_j+d_j=q_j ,即 q j + 1 q_j+1 种选择,所以我们可以得到 n n 的二平方和的方案数(非本质不同)为 4 j = 0 C ( q j + 1 ) 4\prod_{j=0}^C(q_j+1) 。而对于求所有解,只需要将 n n 分解之后对 c j , d j c_j,d_j 暴力即可。

那么还需要解决的问题就是求出 p 1 m o d    4 p\equiv 1 \mod 4 时的二平方和的解,继续设 x 2 1 m o d    p x^2\equiv -1\mod p ,那么我们有:
a 2 + 1 = m p a^2+1=mp
考虑将 m m 减少,并同时保持左边的平方和合法。我们将在处理的式子当作:
a 2 + b 2 = m p a^2+b^2=mp
那么设:
a x m o d    m b y m o d    m a\equiv x\mod m\\ b\equiv y \mod m
有:
x 2 + y 2 = k m ( a 2 + b 2 ) ( x 2 + y 2 ) = p m 2 k ( a x + b y ) 2 + ( a y b x ) 2 = p m 2 k x^2+y^2=km\\ (a^2+b^2)(x^2+y^2)=pm^2k\\ (ax+by)^2+(ay-bx)^2=pm^2k
注意到:
a x + b y x 2 + y 2 0 m o d    m a y b x x y y x 0 m o d    m ax+by\equiv x^2+y^2\equiv 0\mod m\\ ay-bx\equiv xy-yx\equiv 0\mod m
最终有:
( a x + b y m ) 2 + ( a y b x m ) 2 = k p (\frac {ax+by}m)^2+(\frac {ay-bx} m)^2=kp
因为 m 2 < x , y m 2 -\frac m 2<x,y\le \frac m 2 ,所以:
x 2 + y 2 = k m 2 m 2 4 = m 2 2 k m 2 x^2+y^2=km\le \frac{2m^2}4=\frac {m^2} 2\\ k\le \frac m 2
由此,我们可以在 O ( l o g p ) O(logp) 下求出 a 2 + b 2 = p a^2+b^2=p 的一组解。

最后计算一下暴力产生的复杂度,考虑最坏情况,即 n n 都由模 4 4 1 1 的素数组成时, 4 j = 0 C ( q j + 1 ) = σ ( n ) = O ( n ) 4\prod_{j=0}^C(q_j+1)=\sigma(n)=O(\sqrt n) ,但对于满足条件的素数,这个界是非常松的:
20 ! > 1 0 18 20!>10^{18} ,知道前20个模 4 4 1 1 的素数的积必然大于 1 0 18 10^{18} ,同时我们知道,对于给定的 K K ,当 M A X { a i } M I N { a j } 1 MAX\{a_i\}-MIN\{a_j\}\le 1 时, i = 0 n a i i = 0 n a i = K \prod_{i=0}^na_i|\sum_{i=0}^na_i=K 得到最大值,同时显然的,最大因子数随幂数和递增,于是我们计算幂数和为 l o g 5 1 0 18 = 26 \lceil log_510^{18}\rceil=26 时的最大因子数,即 3 6 × 2 14 = 11943936 3^6\times2^{14}=11943936 。所以由模 4 4 1 1 的素数组成的不大于 1 0 18 10^{18} 的数的因子数不会超过 11943936 11943936 ,当然实际的值会比这个值小很多。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
//--Container
//--
typedef __int128 ll;

ll qni(ll a,ll b,ll md){
    ll r=1;for(;b;b>>=1,a=a*a%md)if(b&1)r=r*a%md;
    return r;
};
ll _P,_W;
struct vt{
    ll a,b;
    vt(ll _a=0,ll _b=0):a(_a),b(_b){};
    friend vt operator*(vt&,vt&);
};
vt operator*(vt&a,vt&b){
    return vt((a.a*b.a+_W*a.b%_P*b.b)%_P,(a.a*b.b+a.b*b.a)%_P);
};
vt vqni(vt a,ll b){
    vt r(1,0);for(;b;b>>=1,a=a*a)if(b&1)r=r*a;
    return r;
};
inline ll _ck(ll n){n%=_P;return (n+_P)%_P;};
ll _xq(ll x,ll n){
    if(qni(x,(n-1)>>1,n)==n-1)return -19260817;
    ll t;for(_P=n;;){
        t=rand();if(qni(_ck(t*t-x),(n-1)>>1,n)==n-1)break;
    }
    _W=_ck(t*t-x);
    return vqni(vt(t,1),(n+1)>>1).a;
};

struct vi{
    ll a,b;
    vi(ll _a=0,ll _b=0):a(_a),b(_b){};
    friend vi operator*(vi,vi);
};
vi operator*(vi a,vi b){
    return vi(a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a);
};
void _dss(ll&a,ll&b,ll m){
    ll x,y,t,k,d;for(;m>1;){
        x=a%m,y=b%m;
        if(x>m/2)x-=m;
        if(y>m/2)y-=m;
        k=(x*x+y*y)/m;
        d=(a*x+b*y)/m,t=(a*y-b*x)/m;
        m=k,a=d,b=t;
    }
};
void _p1s(ll p,ll&a,ll&b){
    ll t=_xq(p-1,p);int i,j,k,d;
    _dss(a=t,b=1,(t*t+1)/p);
};

//--TEMPLATE
const int S=2;
ll mult_mod(ll a,ll b,ll c)
{
    a%=c;
    b%=c;
    ll ret=0;
    while(b)
    {
        if(b&1){ret+=a;ret%=c;}
        a<<=1;
        if(a>=c)a%=c;
        b>>=1;
    }
    return ret;
}
ll pow_mod(ll x,ll n,ll mod)
{
    if(n==1)return x%mod;
    x%=mod;
    ll tmp=x;
    ll ret=1;
    while(n)
    {
        if(n&1)ret=mult_mod(ret,tmp,mod);
        tmp=mult_mod(tmp,tmp,mod);
        n>>=1;
    }
    return ret;
}
ll check(ll a,ll n,ll x,ll t)
{
    ll ret=pow_mod(a,x,n);
    ll last=ret;
    for(int i=1;i<=t;i++)
    {
        ret=mult_mod(ret,ret,n);
        if(ret==1 && last!=1 &&last!=n-1)return true;
        last=ret;
    }
    if(ret!=1)return true;
    return false;
}
bool Miller_Rabin(ll n)
{
    if(n<2)return false;
    if(n==2)return true;
    if((n&1)==0)return false;
    ll x=n-1;
    ll t=0;
    while((x&1)==0){x>>=1;t++;}
    for(int i=0;i<S;i++)
    {
        ll a=rand()%(n-1)+1;
        if(check(a,n,x,t))
            return false;
    }
    return true;
}

ll factor[100];
int tol;
ll gcd(ll a,ll b)
{
    if(a==0)return 1;
    if(a<0)return gcd(-a,b);
    while(b)
    {
        ll t=a%b;
        a=b;
        b=t;
    }
    return a;
}

ll Pollard_rho(ll x,ll c)
{
    ll i=1,k=2;
    ll x0=rand()%x;
    ll y=x0;
    while(1)
    {
        i++;
        x0=(mult_mod(x0,x0,x)+c)%x;
        ll d=gcd(y-x0,x);
        if(d!=1&&d!=x)return d;
        if(y==x0)return x;
        if(i==k)
        {
            y=x0;
            k+=k;
        }
    }
}

void findfac(ll n)
{
    if(Miller_Rabin(n))
    {
        factor[tol++]=n;
        return;
    }
    ll p=n;
    while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1);
    findfac(p);
    findfac(n/p);
}
//--https://www.cnblogs.com/kuangbin/archive/2012/11/11/2765525.html

int sm[70],pn;vi vr[70][70];ll n;
vi rss[1000010];int rsn;
vi _cl(bool&fg){
    int i,j,k,d,t;vi rs(1,0);ll a,b,dn=n,qs;for(pn=i=0;i<tol;++i){
        for(qs=1,d=0;!(dn%factor[i]);dn/=factor[i],++d);
        if(factor[i]==2){
            vi tz(1,0);for(j=0;j<d;++j)tz=tz*vi(1,1);
            rs=rs*tz;
        }
        else if(factor[i]%4==3){
            if(d&1){fg=0;return vi(19260817,19260817);}
            for(qs=1,j=0;j<(d>>1);++j,qs*=factor[i]);
            rs=rs*vi(qs,0);
        }
        else{
            sm[pn]=d;vi tz(1,0);_p1s(factor[i],a,b);for(j=d;j>=0;--j,tz=tz*vi(a,-b))
                vr[pn][j]=tz;
            for(tz=vi(1,0),j=0;j<=d;++j,tz=tz*vi(a,b))
                vr[pn][j]=vr[pn][j]*tz;
            ++pn;
        }
    }
    return rs;
};
void dfs(int d,vi rs){
    if(d==pn){rss[rsn++]=rs;return;}
    int i;for(i=0;i<=sm[d];++i){
        dfs(d+1,rs*vr[d][i]);
    }
};

bool vimp(const vi&a,const vi&b){
    return a.a==b.a?a.b<b.b:a.a<b.a;
};

void _sca(ll&n){
    n=0;char t;for(t=getchar();t<'0'||t>'9';t=getchar());
    n=t-'0';for(t=getchar();t>='0'&&t<='9';t=getchar())
        n=n*10+t-'0';
};
void _prt(ll n){
    if(n>9)_prt(n/10);
    putchar(n%10+'0');
};

void cl(){
    int i,j,k;_sca(n);findfac(n);
    sort(factor,factor+tol);tol=unique(factor,factor+tol)-factor;
    bool fg=1;vi rs=_cl(fg);
    if(!fg)printf("No Solution\n");
    else{
        rsn=0;dfs(0,rs);
        for(i=0;i<rsn;++i){
            rss[i].a=abs(rss[i].a),rss[i].b=abs(rss[i].b);
            if(rss[i].a>rss[i].b)swap(rss[i].a,rss[i].b);
        }
        for(sort(rss,rss+rsn,vimp),i=0;i<rsn;i=j){
            for(j=i+1;j<rsn&&rss[i].a==rss[j].a&&rss[i].b==rss[j].b;++j);
            _prt(rss[i].a);putchar(' ');_prt(rss[i].b);putchar('\n');
        }
    }
};

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    cl();
    return 0;
};

猜你喜欢

转载自blog.csdn.net/u012345506/article/details/82889541