zoukankan      html  css  js  c++  java
  • 清北学堂 day6 花

    1.花
    flower.cpp/c/pas
    【 问题描述】
    商店里出售 n 种不同品种的花。为了装饰桌面,你打算买 m 支花回家。你觉得放两支一
    样的花很难看,因此每种品种的花最多买 1 支。求总共有几种不同的买花的方案? 答案可能
    很大,输出答案 mod p 的值。
    【 输入格式】
    一行 3 个整数 n, m, p, 意义如题所述。
    【 输出格式】
    一个整数,表示买花的方案数。
    【输入输出样例 1

    flower.in flower.out
    4 2 5 1


    见选手目录下的 flower / flower1.in flower / flower1.out
    【输入输出样例 1 说明】
    用数字 1,2,3,4 来表示花的种类的话,4 种花里买各不相同的 2 支的方案有(1,2)、(1,3)、
    (1,4)、 (2,3)、 (2,4)、 (3,4), 共 6 种方案, 模 5 后余数是 1。
    【输入输出样例 2
    见选手目录下的 flower / flower2.in flower / flower2.out
    【 数据范围】
    对于 30%的数据, n,m10
    对于 50%的数据, n,m1000
    对于 80%的数据, 1mn50,000
    对于 100%的数据, 1mn1,000,000, p1,000,000,000

     

    解:100分:运用组合数公式:C(n,m)=n!/(m!*(n-m)!)

    因为范围较大,所以进行质因数分解以约分,先打出质数表,最后直接寻找剩余质数并进行乘法取模即可;(必要时可使用快速幂与快速加)。

    开 long #include<iostream>

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #define man 1000010
    #define sc(x) scanf("%lld",&x)
    #define mem(x) memset(x,0,sizeof(x))
    #define ll long long
    using namespace std;
    ll used[man],prime[man],tot=0,aa=1;
    bool isp[man];
    int  n,m,p;
    inline void mkp(int x)
    {
        for(int i=2;i<=x;i++)
        {
            if(!isp[i])
            {    prime[++tot]=i;
                }
            for(int j=1;j<=tot&&i*prime[j]<=x;j++)
            {
                isp[i*prime[j]]=1;
                if(i%prime[j]==0)
                    break;
                }
            }
        }
    void calc1(int x)//n
    {    
        int ans=x;
        for(int i=1;i<=tot;i++)
        {    
            if(ans%prime[i]==0)
            {
                int t=0;
                while(ans%prime[i]==0)
                {
                    ans=ans/prime[i];
                    t++;
                    }
                used[prime[i]]+=t;    
                }
            if(!isp[ans])
            {    used[ans]++;
                ans=1;
                }
            if(ans==1)
                break;
            }
        }
    void calc2(int x)//m&(n-m)
    {    
        int ans=x;
        for(int i=1;i<=tot;i++)
        {
            if(ans%prime[i]==0)
            {
                int t=0;
                while(ans%prime[i]==0)
                {
                    ans=ans/prime[i];
                    t++;
                    }
                used[prime[i]]-=t;    
                }
            if(!isp[ans])
            {    used[ans]--;
                break;
                }
            if(ans==1)
                break;
            }
        }
    ll badd(ll a,ll b,ll c)//快速加
    {
        ll ans=0,bas=a;
        while(b)
        {
            if(b&1) ans=(ans+bas)%p;
            bas=(bas+bas)%p;
            b>>=1;
            }
        return ans;
        }
    ll bpow(ll a,ll b,ll c)//快速幂
    {
        int  ans=1,bas=a;
        while(b)
        {
            if(b&1) ans=(ans*(bas%p))%p;
            bas=((bas%p)*(bas%p))%p;
            b>>=1;
            }
        return ans;
        }
    int main()
    {    freopen("flower.in","r",stdin);
        freopen("flower.out","w",stdout);
        mem(prime);mem(used);mem(isp);
        sc(n);sc(m);sc(p);
        mkp(n);
        for(int i=2;i<=n;i++)//对n!质因数分解
        calc1(i);
        for(int i=2;i<=m;i++)//对m!质因数分解
        calc2(i);
        for(int i=2;i<=n-m;i++)//对(n-m)!质因数分解
        calc2(i);
        for(int i=1;i<=tot;i++)
        {    
            if(used[prime[i]]>0)
            {    
                aa=badd(aa,bpow(prime[i],used[prime[i]],p),p);
                }
            }
        printf("%lld
    ",aa);
        return 0;
        }
    欢迎大家吐槽或评论,如要转载请注明地址,谢谢~(虽然不一定有人能看到。。。)
  • 相关阅读:
    个人博客
    个人博客
    5.4
    4.30
    4.29
    4.28
    4.27
    4.26
    4.25
    4.24
  • 原文地址:https://www.cnblogs.com/Slager-Z/p/7440992.html
Copyright © 2011-2022 走看看