1. 程式人生 > >總結:數論 素數

總結:數論 素數

如果 mil rdo return urn 因子 素數 高效 rand

素數判定算法,經典的Rabin Miller測試,通過二次探測的方法,可以將其正確率上升到一個很高的高度。

$O(1)$的快速乘。

在一些卡常數而且爆long long的取余問題中用到快速乘。

樸素的快速乘是$O(logn)$的,從而添加了不必要的復雜度。

爆long long的,實質上是取余的結果,在long long運算中只要不涉及除法,那麽一直是對INF取余的結果,對答案沒有幹擾。

1 LL mul(LL a,LL b,LL mod){
2     if(a<=(LL)(1e8) && b<=(LL)(1e8)) return a*b%mod;
3 return (a*b - (LL)(a/(LD)mod*b + 1e-3)*mod + mod) % mod; 4 }

註意快速乘在很小的數字時並不太穩,所以特判一下。

註意一下Linux下rand()函數足夠大,不需要拓充。

轉入正題:Rabin測試。

我的Rabin在INT範圍內不會出錯,在LOGN LONG範圍內出錯的概率極低。

首先是寫一個check(LL x,LL P),用數字x檢驗P是否為素數。

 1 bool check(LL x,LL P){
 2     LL tmp=P-1;
 3     while(!(tmp&1)) tmp>>=1
; 4 LL m=qpow(x,tmp,P); 5 if(m==1) return 1; 6 while(tmp<P){ 7 if(m==P-1) return 1; 8 tmp<<=1; m=mul(m,m,P); 9 } 10 return 0; 11 }

梳理一下過程

首先將P-1中所有的2全都除掉。

這時候如果tmp 為 P-1 或者 1是偽素數。(具體就用 $x^{tmp} = 1 (mod P)$判定)

這時候檢查$x^{2tmp} , x^{4tmp}, x^{8tmp} ....$是否等於 $P-1$。

如果沒有則說明P不是素數。

接下來基於這一個$O(logn)$判定素數,我們有$O(n^{1/4})$的分解質因數算法。

Rho算法。

Rho算法是基於一個定理對於一個小於n的數字x如果 $(x,n) ≠ 1$ 則有,(x,n)為n的因子。

這樣考慮怎樣高效地得到這樣的數字x。

 1 LL Rdo(LL n,LL c){
 2     LL i=1,k=2,x,y,d,p;
 3     x=Rand()%n;
 4     y=x;
 5     while(1){
 6         i++;
 7         x=(mul(x,x,n)+c)%n;
 8         if(y==x) return n;
 9         p=Abs(x-y);
10         d=gcd(p,n);
11         if(d!=1&&d!=n) return d;
12         if(i==k){
13             y=x;
14             k+=k;
15         }
16     }
17 }
18 
19 int tot;
20 LL a[N];
21 
22 void down(LL n){
23     if(n==1) return;
24     if(isprime(n)){
25         a[++tot]=n;
26         return;
27     }
28     LL t=n;
29     while(t==n) t=Rdo(n,Rand()%(n-1)+1);
30     down(t);
31     down(n/t);
32 }

這樣就可以得到了分解質因數的高效方法。

註意一個數字的質因子最多有$O(logn)$個,因為質因數的乘積為n,而且質因數都大於1.

註意在隨機數據情況下,采用樸素分解質因數的效率也大概接近 $O(n^{\frac{1}{4}})$,只不過會受到空間的限制。

for(int i=1;prime[i]*(LL)prime[i]<=tmp;i++)
{
    int cnt = 0;
    tim_cnt++;
    while(tmp % prime[i] == 0) tmp /= prime[i];
    ans *= (cnt+1);
}

註意是 <=tmp 而不是 <=n

給定一個整數N,求N最少可以拆成多少個完全平方數的和。

所以根據拉格朗日平方和定理,答案為1~4

答案為1,開方驗證

答案為2,根據勾股數定理一個數字為勾股數當且僅當其質因數分解中所有的$4n+3$項的指數為偶數。

答案為3,根據初等數論中的不等式 $n ≠ (8k + 7) \cdot 4^{m}$

不然答案為4,根據 拉格朗日平方和定理即可。

總結:數論 素數