<题目链接>
题目大意:
给出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,为质数,所以可以用费马小定理求逆元。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define LL long long using namespace std; const LL MOD=1e9+7; const LL MAXN=1e6+10; LL a,b; LL n; LL fact[MAXN];//存i的阶乘 bool Sum_ok(LL x){ while(x){ //判断每一位是否只由a或b组成 LL res=x%10; if(res!=a&&res!=b) return false; x=x/10; } return true; } LL pow(LL m,LL n){ if(n==0) return 1; LL ans=1; while(n>0){ if(n&1) ans=ans*m%MOD; m=m*m%MOD; n=n/2; } return ans; } int main(){ scanf("%d %d %d",&a,&b,&n); fact[0]=1; for(LL i=1;i<=n;i++) fact[i]=fact[i-1]*i%MOD;//将fact数组初始化将阶乘的值存进数组,不要忘了取余 LL ans=0; for(LL i=0;i<=n;i++){ //枚举a的个数 if(is_gnum(a*i+b*(n-i))){ //判断枚举出的数是不是good number LL t1=pow(fact[i],MOD-2)%MOD; //费马小定理求逆元,注意求逆元的格式,fact[i]、fact[n-i]均为除数 LL t2=pow(fact[n-i],MOD-2)%MOD; ans += fact[n]*t1%MOD*t2%MOD;//利用上面讲解中推导出的公式计算出答案,利用组合数公式,n!/(m!*(n-m)!) } } printf("%lld\n",ans%MOD); return 0; }
2018-10-09
原文地址:https://www.cnblogs.com/00isok/p/9762172.html
时间: 2024-10-10 12:55:22