1. 程式人生 > >POJ-2992 Divisors---組合數求因子數目

POJ-2992 Divisors---組合數求因子數目

ios 階乘 素數 oid rim 預處理 tro image ()

題目鏈接:

https://cn.vjudge.net/problem/POJ-2992

題目大意:

給出組合數Cnk,求出其因子個數,其中n,k不大於431,組合數的值在long long範圍內

解題思路:

由於只有431種階乘,先預處理431中素數,再預處理出每一個階乘裏面所含的素因子的指數,然後對於組合數,直接用素因子指數相減即可。

求出的質因子指數,就可以用定理直接求因子個數。

技術分享圖片

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 using namespace std;
 5 typedef long
long ll; 6 bool not_prime[1000]; 7 int prime[200], tot; 8 void sieve(int n) 9 { 10 for(int i = 2; i <= n; i++) 11 if(!not_prime[i]) 12 { 13 prime[tot++] = i; 14 for(int j = i * 2; j <= n; j += i) 15 not_prime[j] = 1; 16 } 17 } 18 int a[500][100];//a[i][j]表示i的階乘中素數prime[j]的指數
19 void init(int n) 20 { 21 for(int i = 2; i <= n; i++) 22 { 23 for(int j = 0; j < tot && prime[j] <= n; j++) 24 { 25 if(i % prime[j] == 0) 26 { 27 int t = i; 28 while(t % prime[j] == 0) 29 {
30 t /= prime[j]; 31 a[i][j]++; 32 } 33 } 34 a[i][j] += a[i - 1][j]; 35 } 36 } 37 /*for(int i = 1; i <= 50; i++) 38 { 39 for(int j = 0; j < tot; j++) 40 { 41 if(a[i][j]) 42 { 43 printf("%d %d %d\n", i, prime[j], a[i][j]); 44 } 45 } 46 }*/ 47 } 48 int main() 49 { 50 sieve(431); 51 init(431); 52 int n, k; 53 while(scanf("%d%d", &n, &k) != EOF) 54 { 55 int ant[100]; 56 for(int i = 0; i < tot; i++) 57 ant[i] = a[n][i] - a[k][i] - a[n - k][i]; 58 ll ans = 1; 59 for(int i = 0; i < tot; i++) 60 ans *= (ant[i] + 1); 61 printf("%lld\n", ans); 62 } 63 return 0; 64 }

POJ-2992 Divisors---組合數求因子數目