• 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
     
  • 相关阅读:
    消息中间件(一)MQ详解及四大MQ比较
    WebSocket 详解教程
    Nginx 简易教程
    排序七 归并排序
    排序五 简单选择排序
    排序四 希尔排序
    排序二 快速排序
    排序一 冒泡排序
    [算法题] 人民币大小写转换(阿拉伯数字和汉字转换)
    Linux编程 18 安装软件程序(yum工具对软件包安装,删除,更新介绍)
  • 原文地址:https://www.cnblogs.com/cshg/p/5779090.html
Copyright © 2020-2023  润新知