- 求卡特蘭數 (其實就是組合數)
- 大組合數且模數非素數,無法求逆元
- 高精組合數,如果你不想打高精除的話(沒人想打)
方法:
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 }
同理對分母分解,然后我們只要--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很大,或分解次數很少的情況,第二種更優。