Poj2992Divisors 组合数求因子的个数

 

Description

Your task in this problem is to determine the number of divisors of Cnk. Just for fun -- or do you need any special reason for such a useful computation?

Input

The input consists of several instances. Each instance consists of a single line containing two integers n and k (0 ≤ k ≤ n ≤ 431), separated by a single space.

Output

For each instance, output a line containing exactly one integer -- the number of distinct divisors of Cnk. For the input instances, this number does not exceed 263 - 1.

Sample Input

5 1
6 3
10 4

Sample Output

2
6
16

Source

题目大意:求组合数Cnk因子的个数
 如果用暴力的做法肯定会TLE的, 那么该怎么做呢?
 定理1, 设f(N) 为N因子的个数 , pi为质因子, ai为该质因子的个数
把N质因数分解得到 N = p1^a1 * p2^a2 * p3^a3*……*pi^ai
f(N) = (a1 + 1)*(a2 + 1) * (a3 + 1)*……*(ai + 1);
那么怎么求N! 呢
定理2,设每个质因子指数的个数为ei,  ei = [N/pi] + [N/(pi^2)] +[N/(pi^3)] +……+[N/(pi^i)]  直到 N/(pi^i) = 0
f(N!) = (e1 + 1)*(e2 + 1) *(e3 + 1)*……*(ei + 1)
Cnk = n! / (k! * (n - k)!)
首先打个素数表, 遍历一遍即可
 
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
#include <cstring>

using namespace std;


typedef long long int ll;
typedef pair<int, int> P;
int read() {
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
const double pi=3.14159265358979323846264338327950288L;
const double eps=1e-6;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int INT = 0x7fffffff;
const int MAXN = 433;
const int xi[] = {0, 0, 1, -1};
const int yi[] = {1, -1, 0, 0};

int N, T;
int a[MAXN], cnt;//cnt记录素数的个数

void init() {//求素数
    cnt = 0;
    for(int i = 2; i <=431 ; i++) {
        int flag = 1;
        for(int j = 2; j*j <= i; j++) {
            if(i%j == 0) {
                flag = 0;
                break;
            }
        }
        if(flag) {
            a[cnt++] = i;
        }
    }
}
inline int cal(int n, int k){//计算指数的个数
   if(n < k) return 0;
   return n/k + cal(n/k, k);
}
int main() {
    init();
    int n, k;
    while(~scanf("%d%d", &n, &k)){
          ll  res = 1LL;
        for(int i = 0; i < cnt; i++){//遍历
            res *= 1LL*(cal(n, a[i]) - cal(k, a[i]) - cal(n-k, a[i]) + 1);
        }
        printf("%lld
", res);

    }

    return 0;
}
View Code
 
原文地址:https://www.cnblogs.com/cshg/p/5779090.html