Codeforces 300C Beautiful Numbers 【组合数】+【逆元】

<题目链接>

题目大意:

给出a和b,如果一个数每一位都是a或b,那么我们称这个数为good,在good的基础上,如果这个数的每一位之和也是good,那么这个数是excellent。求长度为n的excellent数的个数mod(1e9+7)。

解题分析:

我们可以枚举a的个数m,所以b的个数为(n-m),然后判断这种情况是否可行,即,是否满足a*m+b*(n-m)为good number ,如果满足的话,则答案加上C(n,m)。因为n很大,并且在计算组合数的过程中,需要除以很大的数,所以需要求逆元,因为本题模数为1e9+7,为质数,所以可以用费马小定理求逆元。组合数计算公式如下:

$$C(n,m)=frac{n!}{(n-m)!*m!}(m≤n)$$

所以,我们需要对$(n-m)!$和$m!$求逆元

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll mod = 1e9+7;
const int N = 1e6+5;
ll n,a,b,fact[N];

bool isgood(ll x){     //判断和是否也是good
  while(x){
    ll res=x%10;
    if(res!=a&&res!=b)return false;
    x/=10;
  }return true;
}

ll pw(ll a,ll b){
  if(b==0)return 1;
  ll ans=1;
  while(b){
    if(b&1)ans=ans*a%mod;
    a=a*a%mod;
    b>>=1;
  }return ans;
}
int main(){
  cin>>a>>b>>n;
  fact[0]=1;
  for(int i=1;i<=n;i++)fact[i]=fact[i-1]*i%mod;
  ll ans=0;
  for(int i=0;i<=n;i++){
    if(isgood(a*i+b*(n-i))){
      ll tmp1=pw(fact[i],mod-2)%mod;       //费马小定理求逆元
      ll tmp2=pw(fact[n-i],mod-2)%mod;
      ans+=fact[n]*tmp1%mod*tmp2%mod;     
    }
  }
  printf("%lld
",ans%mod);
}
原文地址:https://www.cnblogs.com/00isok/p/9762172.html