• POJ 2992


    POJ 2992

    [题目大意]

    求组合C(n,k)的全部因子个数。

    [核心要点](数论基本知识)

    第一:C(n,k) = n! / k! / (n - k )!

    无需证明,可自己推导

    第二:对于所有正整数n,都可按素因子分解为n=p1^a1*p2^a2*....*pk^ak(其中pi均为素数),那么n的约数的个数为(a1+1)(a2+1)...(ak+1);

    例如:12 = 2 ^ 2 * 3 ; 12 的约数个数有(2 + 1) * (1 + 1) = 6个(1 ,2 ,3 ,4 ,6 ,12);

    (不会证明qaq) 

    第三:对于一个素数p,n!中按素因子分解,p的幂为 n/p+n/p^2+n/p^3...,其中/为整除;

    即,ai = n/pi+n/pi^2+n/pi^3...

    例如:4!(24 ) = 2 ^ 3 * 3 ;其中,2的幂次为 4 / 2 + 4 / 2 ^ 2 = 3 ; 3的幂次为 4 / 3 = 1;

    (不会证明qaq)

    第四:基于以上第三点,推导如下:

    设n!中素因子p的个数为:a=n / p+n / (p^2)+...+n / (p^k)+...

    那么(n/p)!中素因子p的个数为:b = n/(p^2)+...+n/(p^k)+...

    很显然a=b+n/p,因此可以利用上述递推公式预处理出所有的j!中每个素因子的个数。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    
    typedef long long ll;
    
    using namespace std;
    
    const int N = 500; 
     
    bool Prime[N];
    int jie[N][90];
    ll zu[N][N];
    int Primer[N],num;
    
    //在Prime[500]打素数表 
    void GetPrime()
    {
        for(int i = 2; i <= 431; ++i)
            Prime[i] = true;
        for(int i = 2; i <= 431; ++i)
        {
            if(Prime[i])
            {
                for(int j = i+i; j <= 431; j+=i)
                    Prime[j] = false;
            }
        }
        num = 0;
        for(int i = 0; i <= 431; ++i)
        if(Prime[i])	Primer[num++] = i;
    }
     
    void solve()
    {
        //阶乘分解为 素因子相乘的形式jie[j][i]表示 j! 第i个素数的幂为多少
        for(int i = 0;i < num; ++i)
            for(int j = 2; j <= 431; ++j)
                jie[j][i] = j/Primer[i] + jie[j/Primer[i]][i];
     
        for(int i = 2; i <= 431; ++i)   //计算因子个数
        {
            for(int j = 1; j < i; ++j)
            {
                zu[i][j] = 1;
                for(int k = 0; k < num && jie[i][k]; ++k)
                {
                    int side = jie[i][k] - jie[j][k] - jie[i-j][k]; //计算C(i,j)中第i个素数的幂为多少
                    if(side)
                        zu[i][j] *= (side+1);   //求因子个数
                }
            }
        }
    }
     
    int main()
    {
        GetPrime();
        solve();
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            if(m==0 || m==n)
                printf("1
    ");
            else
                printf("%I64d
    ",zu[n][m]);
        }
     
        return 0;
    }
    

    [Reference]

    https://blog.csdn.net/lianai911/article/details/44598155#commentBox   https://blog.csdn.net/u011008379/article/details/20408063

    数论部分强烈推荐

    http://www.cnblogs.com/linyujun/p/5198832.html#3970365

    透过泪水看到希望
  • 相关阅读:
    java 下载图片并传输(java自带 BASE64工具进行图片和字符串转换)
    MySQL的日期格式
    eclipse下查看maven下载的源码中文乱码问题
    Linux----部署
    python----logging
    python----pymysql
    vmware15 激活秘钥
    vmware15 激活秘钥
    Ubuntu18.04安装
    msyql45讲 20--幻读是什么,幻读有什么问题?
  • 原文地址:https://www.cnblogs.com/ronnielee/p/9495155.html
Copyright © 2020-2023  润新知