zoukankan      html  css  js  c++  java
  • 花(cnm加强)

    【问题描述】
    商店里出售n种不同品种的花。为了装饰桌面,你打算买m支花回家。你觉得放两支一样的花很难看,因此每种品种的花最多买1支。求总共有几种不同的买花的方案?答案可能很大,输出答案mod p的值。

    【输入格式】
    一行3个整数n,m,p,意义如题所述。

    【输出格式】
    一个整数,表示买花的方案数。
    【输入输出样例1】
    4 2 5
    1
    【输入输出样例1说明】
    用数字1,2,3,4来表示花的种类的话,4种花里买各不相同的2支的方案有(1,2)、(1,3)、(1,4)、(2,3)、(2,4)、(3,4),共6种方案,模5后余数是1。

    【数据范围】
    对于30%的数据,n,m≤10
    对于50%的数据,n,m≤1000
    对于80%的数据,1≤m≤n≤50,000
    对于100%的数据,1≤m≤n≤1,000,000,p≤1,000,000,000

    n^2的杨辉三角肯定不行。
    因为p不一定是质数,所以用费马小定理求逆元也不行。
    只能用分解质因数。
    数据很强,要用到快速幂,线性质数筛。
    注意剪枝和利用开方降低时间复杂度。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define LL long long
    using namespace std;
    LL n,m,p;
    LL ans;
    int num[1000009],prime[1000009],cnt;
    bool notp[1000009];
    void Prime()
    {
        notp[0]=1,notp[1]=1;
        for(LL i=2;i<=n;i++)
        {
            if(!notp[i]) prime[++cnt]=i;
    
            for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
            {
                notp[i*prime[j]]=1;
                if(i%prime[j]==0) break;
            }
        }
    }//线性筛素数
    LL Fast_pow(LL x,LL k)
    {
        LL a1=1;
        x%=p;
        while(k)
        {
            if(k%2) a1=a1*x%p;
            x=(x*x)%p;
            k/=2;
        }
        return a1;
    }
    void tear(LL x,int d)
    {
        LL r=(sqrt(x)+0.5);
        for(LL i=1;i<=cnt;i++)
        {
            if(!notp[x]) {num[x]+=d;return;}  //剪枝
            LL k=prime[i];
            if(k>r) break;//剪枝
            while(x%k==0)
            {
                num[k]+=d;
                x/=k;
            }
        }
        if(x>1) num[x]+=d;
    }
    void get_ans()
    {
        ans=1;
        for(LL i=2;i<=n;i++)
        {
            if(num[i])
            {
                ans=(ans*Fast_pow(i,num[i]))%p;
            }
        }
    }
    int main()
    {
        //freopen("flower.in","r",stdin);
        //freopen("flower.out","w",stdout);
    
        scanf("%lld%lld%lld",&n,&m,&p);
    
        Prime();
    
        for(LL i=m+1;i<=n;i++) tear(i,1);
        for(LL i=2;i<=n-m;i++) tear(i,-1);
        get_ans();
        printf("%lld",ans);
        return 0;
    } 
  • 相关阅读:
    qt creator中输入中文中文变繁体
    Trie
    pycharm 专业版的 django功能
    fzu 1533
    django使用问题记录
    查看SQLServer最耗资源时间的SQL语句
    从mysql数据库删除重复记录只保留其中一条(保留id最小的一条)
    使用CSS3的appearance属性改变元素的外观
    mysql中将多行数据合并成一行数据
    MySQL字符串的拼接、截取、替换、查找位置
  • 原文地址:https://www.cnblogs.com/dfsac/p/7587792.html
Copyright © 2011-2022 走看看