组合数学

题目:

很好的组合数学。

代码:

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int max_=2e5+2;
ll F[max_],Finv[max_];
int a;
bool check(int s)
{
    while(s)
    {
        if(s%10!=4&&s%10!=7)
            return 0;
        s/=10;
    }
    return 1;
}
ll pow_mod(ll x,ll n)
{
    x%=mod;
    ll res=1;
    while(n)
    {
        if(n&1)
            res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}
ll inv(ll x)//逆元
{
    return pow_mod(x,mod-2);
}
void factrial()//阶乘
{
    F[0]=1,Finv[0]=1;
    for(ll i=1;i<max_;i++)
    {
        F[i]=F[i-1]* 1ll *i%mod;//n数组的阶乘
        Finv[i]=Finv[i-1]*inv(i)%mod;//n数组逆元的阶乘
    }
}
ll C(ll n,ll m)//组合数,从n个选出m个,combination
{
    if(m<0||m>n)
        return 0;
    else
       return F[n]*Finv[n-m]%mod*Finv[m]%mod;
}
map<ll,ll>mp;
int main()
{
    ll n,m;
    factrial();//求出数组
    cin>>n>>m;
    ll coun=0;
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a);
        if(mp[a]&&check(a))
            coun++;//记录重复不吉利的个数
        else
            mp[a]=1;
    }
    ll x=n-coun;
    //cout<<C(4,2)<<endl;
    //cout<<x<<d<<endl;
    cout<<(C(x,m)+C(x-1,m-1)*coun%mod)%mod<<endl;//从没重复的中选出C(x,m),然后加上去掉一个重复不吉利的数后从重复的集合选
}
View Code
原文地址:https://www.cnblogs.com/linhaitai/p/10020477.html