1. 程式人生 > >「Luogu P2508」[HAOI2008]圓上的整點 解題報告

「Luogu P2508」[HAOI2008]圓上的整點 解題報告

題面

給定圓的半徑,求圓上整點數

這是一道很Nice的數學題!超愛!好吧,由於這道題,我去Study了一下複數(complex number)複雜的數

真棒!!!

有興趣的戳這裡!!!\(\huge \to\)

思路:

高斯素數的原理,將整數分解質因數後,再把每個質因數分解成高斯素數,對於質數4n+1,它可以有效的分解成高斯素數,而質數4n+3不能,因為3無法分解為高斯素數,所以當一個數有奇數個3因子時,這個圓上沒有整點,而3的個數為偶數時,由於能分成兩組配對,所以有整點,但3對Ans的影響為0,因為x*1=x,因此只要不變就行了,當由於2的高斯素數表示為1-i*1+i,所以2的個數對Ans無影響

對於25如下:

\[ \large 25=5 \times 5 \]

\[ \large 25=(2-i)(2+i)(2-i)(2+i) \]

所以:

Left Right
\(\large 1\) \(\large 1\)
\(\large 2-i\) \(\large 2+i\)
\(\large 2-i\) \(\large 2+i\)
\(\large =3-4i\)
\(\large =3+4i\)

這是一種情況\(\large (3,-4)\)

Left Right
\(\large 2-i\) \(\large 2-i\)
\(\large 2+i\) \(\large 2+i\)
\(\large =5\) \(\large =5\)

這是一種情況\(\large (5,0)\)

Left Right
\(\large 2+i\) \(\large 2+i\)
\(\large 2+i\) \(\large 2+i\)
\(\large =3+4i\) \(\large =3-4i\)

這是一種情況\(\large (3,-4)\)

而對於上述

\(\large \times\) \(\large 3-4i\) \(\large 5\) \(\large 3+4i\)
\(\large -1\) \(\large -1+4i\) \(-5\) \(\large -3-4i\)
\(\large i\) \(\large 4+3i\) \(\large 5i\) \(\large -4+3i\)
\(\large -i\) \(\large -4-3i\) \(\large -5i\) \(\large 4-3i\)

所以一共有點對12

那麼高斯素數怎麼表示點呢?

它只要一個數,就可以表示點的座標,RT:

Code:

#include<bits/stdc++.h>
#define N 10000010
#define ll long long
using namespace std;
ll n,m,res,ans=4;
ll a[N],t,T;
ll p[N];
ll s[N];
bool b[N];
int main()
{
    ll i,j;
    scanf("%lld",&n);
    m=n;
    for(i=2;i*i<=m;i++)
    {
        if(!b[i])
        {
            a[++T]=i;
            if(m%i==0)
            {
                p[++t]=i;
                while(m%i==0)
                {
                    m/=i;
                    s[t]++;
                }
            }
        }
        for(j=1;j<=T;j++)
        {
            if(a[j]*i*i*a[j]>m)
                continue;
            b[a[j]*i]=1;
            if(i%a[j]==0)
                continue;
        }
    }
    if(m>1)
    {
        p[++t]=m;
        s[t]=1;
    }
    for(i=1;i<=t;i++)
        if((p[i]-1)%4==0)
            ans*=(2*s[i]+1);
    printf("%lld",ans);
    return 0;
}