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\n",ans%mod); }
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。