zoukankan      html  css  js  c++  java
  • 51nod 2989 组合数

    题目链接:http://class.51nod.com/Challenge/Problem.html#problemId=2989

    一、题目描述

    组合数C(m,n),表示从M个数中选择N个,有多少种不同的方法。

    组合数的计算公式如下:

    给出m,n输出C(m,n)最后9位数,去掉前缀的0。

    输入

    一行,两个正整数N和M(N<=1000000,M<=1000000)。

    输出

    一行,输出C(m,n)最后9位数,去掉前缀的0。

    样例输入

    6 3

    样例输出

    20

    二、思路描述

    求1个数的最后9位且不考虑前缀0,相当于求这个数%1000000000的结果。

    可以将1-n​的每一个数都分解为素数幂的乘积,再统计每个素数的幂之和。

    例如:

    6!=1×2×3×4×5×6 = 2×3×22×5×2×3 = 24×32×5​

    3!=2×3

    我们变成这个样子后就可以进行除法(幂为减法):

    同底数幂相除,底数不变,指数相减:(同样是以2为底数的)
    a÷ a= a(m-n)
    例如:a÷ a= a(5-2) = a3

    并不需要逐个分解1-n​的每一个数,只需要求解出小于n的所有质数,然后套用求解阶乘后面0的方法(https://www.cnblogs.com/elisa02/p/12811208.html),求每个质数的幂次。

    有了每个质因子的幂次后,再套用快速幂来求解(https://www.cnblogs.com/elisa02/p/12793231.html),这样复杂度降为O(nloglogn)。可以处理1e6范围的数据了。

    三、代码

    #include<cstdio>
    #include<iostream>
    using namespace std;
    long long mod = 1000000000;
    
    long long count(long long n, long long p){//在1~n的范围内含有p质因子的幂次之和是多少  
        long long ans = 0;
        for(long long i = p;i <= n;i *= p){
            ans += n/i;
        }
        return ans;
    }
    
    long long p_mod(long long a, long long b, long long m){//a的b次方%m 
        long long ans = 1;
        a = a % m;
        while(b > 0){
            if(b & 1){
                ans = (ans * a) % m;
            }
            a = (a*a) % m;//每一个位置都要乘一次平方 
            b >>= 1;//判断下一个位置了 
        }
        return ans;//返回累积的结果 
    }
    
    int main(){
        long long m, n, ans=1, cnt;
        bool primes[1000010]={0};
        cin >> m >> n;
        if(m < n){
            cout << '0' << endl;
            return 0;
        }
        for(int i = 2;i <= m;i++){
            if(!primes[i]){//如果primes[i]不为质数 
                cnt = count(m, i) - count(n, i) - count(m-n, i);
                ans = (ans * p_mod(i, cnt, mod)) % mod;
                for(long long j = (long long)i*i;j <= m;j += i){//如果primes[i]不为质数
                    //说明他的倍数不是质数  
                    primes[j] = true;
                }
            }
        }
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    bzoj 4583 购物
    hdu 4694 支配树
    弦图问题初步
    第一次省选总结
    初学kd树
    省选前集训 lca
    bzoj 3282 Tree
    bzoj 2157 旅游
    二分图匹配(匈牙利算法模板)
    最大流(模板)
  • 原文地址:https://www.cnblogs.com/elisa02/p/12862489.html
Copyright © 2011-2022 走看看