很好的组合数学。
代码:
#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),然后加上去掉一个重复不吉利的数后从重复的集合选 }