zoukankan      html  css  js  c++  java
  • 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);
    }
  • 相关阅读:
    Bufferedreader和BufferedWriter(带缓存的输入输出)
    FileReader和FileWriter
    Map接口的类实现
    Map接口
    Set集合
    List接口的实现类
    获取文本框或密码框中的内容
    ADTS (zz)
    初级美语 L003:My Family 解析
    初级美语 L001:Self Introduction 解析
  • 原文地址:https://www.cnblogs.com/00isok/p/9762172.html
Copyright © 2011-2022 走看看