一般做組合數的題目都要進行質因數的分解,我們一般是for循環對每個數進行質因數分解,大多數情況都不會超時,但極少數的情況下,題目會不允許這樣的做法,所以我們需要學會一種更快的方法來求質因數。
我們一般的方法是對每個數進行質因數分解:
inline void calc(int x,int val) { int xx=x; for(int i=2;i*i<=xx;i++) { while(x%i==0)//不斷進行除法,找出多少的當前的質數 { c[i]+=val;x/=i; } if(x==1)break; } if(x>1)c[x]+=val;//如果剩下的數也是個質數,那么這個質數也要加上val }
但如果想要更快的分解,我們可以直接對n!進行分解:
首先先進行素數篩選,得出素數表
然后進行如下操作:
1 inline long long calc(int n,int x)//x表示想要求的質數,函數的作用是求出x的個數,n表示要求的n!(例:n=8表示8!) 2 { long long cnt=0; 3 for(long long i=x;i<=n;i*=x)//為了防止i的溢出,所以我們要開long long 4 {cnt+=n/i; 5 } 6 return cnt; 7 }
我們來一個樣例說明一下:
1 2 3 4 5 6 7 8 我們求得在8!中2的個數
1 1 1 1 首先我們先計算出2的倍數的個數:8/2=4
1 1 其次我們計算出4的倍數的個數: 8/4=2(上面一個式子求出了第一層,現在求第二層)
1 最后我們解出第三層的2的個數: 8/8=1
我們把4+2+1=7,所以一共7個2出現了。
即:cnt(x)=[n/(x^1)]+[n/(x^2)]+[n/(x^3)]+...(直到x的次方大於n)
到這里我們可以發現:我們平時求的方法是一列一列求的(就是每一個數算一遍),而這個方法我們每一行每一行的求,雖然效果一樣,但求起來速度很快。值得學習。
故做法:
1.先把素數表打好
2.for循環把小於n的每個質數進行一次運算,用數組記錄
3.結束
非常快。