分解質因數


  • 求卡特蘭數 (其實就是組合數)
  • 大組合數且模數非素數,無法求逆元
  • 高精組合數,如果你不想打高精除的話(沒人想打)

方法:

1

以求高精組合數為例

一般地,對於$n m \leq 10^6$ 可以打素數表,然后在mark i*prime[j]時附上標記prime[j]  其實就是i*prime[j] 的最小質因數,這樣可以在分解時將復雜度控制在$O(logn)$以下。

 1 void get_prime()
 2 {
 3     F(i,2,n)
 4     {
 5         if(!mark[i])
 6         {
 7             prime[++pc]=i;
 8             mark[i]=i;
 9         }
10         F(j,1,pc)
11         {
12             if(i*prime[j]>n) break;
13             mark[i*prime[j]]=prime[j];
14             if(i%prime[j]==0) break;
15         }
16     }
17 }
線性篩素數並標記
1 while(x!=1)
2 {
3     ++pz[mark[x]];
4     x/=mark[x];
5 }
對x分解質因數

同理對分母分解,然后我們只要--pz[]就可以了(組合數是整數,所以我們可以預見分母會被約掉)。

1 F(i,2,n) while(pz[i]--) dcheng(a,i);
高精乘低精

實際上pz[]有很多下標是無用的,我們可以讓mark[]存素數的標號(即在prime[]中的下標)。這樣在n m很大時可以減少上面代碼的循環次數。

 

 

2

以下不是求組合數而單論分解。設x為要分解的數

對於x很大(1e9),我們可以用試除法。

枚舉$1~\sqrt{x}$ 對於一個枚舉到的i,除到不能整除為止,記錄因數,顯然這樣得到的因數都是素數。

枚舉完后,若x!=1 則將x加入質因子中。

這樣做的正確性:反證法:假設有兩個>sqrt(x)的質因數,那么將它們相乘會>x,與命題矛盾,得證。

然后我們就可以在$O(\sqrt{x})$下沒有多開一個數組而愉快地解決了問題。

 

總結

兩種算法比較:

1.對於要頻繁分解質因數的情況,第一種更優。只要$O(n)$線性篩一遍,然后單次分解$O(logn)$。所以當估計操作數達到$O(\sqrt(n))$直接第一種

2.對於x很大,或分解次數很少的情況,第二種更優。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM