Loading

CF300C Beautiful Numbers(排列组合/组合数取模)

链接:https://ac.nowcoder.com/acm/contest/21791/F
来源:牛客网

题目描述

给你两个数字 a a和 b b。一个数是由 a,b a,b两种数字构成,那么这个数是good;这个数的每一位加起来构成新的一个数,并且新数也是一个good数,那么称原数为excell。
求 n n位数中有多少个数是excell,输出 mod 109+7 mod 109+7 后的结果。 注意, n n位数不能有前导0。

输入描述:

第一行包含三个整数 a,b,n(1≤a<b≤9,1≤n≤106) a,b,n(1≤a<b≤9,1≤n≤106)。

输出描述:

输出一个整数。表示答案 mod 109+7 mod 109+7 后的结果。

示例1

输入

复制

1 3 3

输出

复制

1

说明

满足条件的三位数只有1个:111。

示例2

输入

复制

2 3 10

输出

复制

165

备注:

原题链接:https://codeforces.com/problemset/problem/300/C

注意到,当一个数是excell的时候,不管怎么排列这个数的每一位,它都是excell的。因此可以枚举含有的a的个数x,进而也可以得到b的个数y。如果x个a和y个b组成的数是excell的话就把答案加上\(C_n^x\)即可(相当于从n个位置选x个位置放a)。计算组合数直接套组合数取模的板子即可。

#include <bits/stdc++.h>
#define mod 1000000007
#define ll long long 
#define LL long long
#define p 1000000007
using namespace std;
ll n, a, b;
bool judge(ll sum) {
	while(sum) {
		ll now = sum % 10;
		sum /= 10;
		if(now != a && now != b) {
			return 0;
		}
	}
	return 1;
}
const long long maxn = 2000005;
void extend_gcd(LL a,LL b,LL &x,LL &y){
    if(b==0){
        x=1,y=0;
        return;
    }
    extend_gcd(b,a%b,y,x);
    y-=a/b*x;
}

ll inv[maxn + 10];
ll f[maxn + 10];
void init(){//阶乘及其逆元打表
    f[0]=1;
    for(int i=1;i<=maxn;i++){
        f[i]=f[i-1]*i%p;
    }

    LL x,y;
    extend_gcd(f[maxn],p,x,y);//先求出f[N]的逆元,再循环求出f[1~N-1]的逆元
    inv[maxn]=(x%p+p)%p;
    for(int i=maxn-1;i>=1;i--){
        inv[i]=inv[i+1]*(i+1)%p;
    }
}

LL C(LL n,LL m){
    if(n==m||m==0)return 1;
    return (f[n]*inv[m]%p*inv[n-m]%p)%p;
}
int main() { 
	init();
	cin >> a >> b >> n;
	ll ans = 0;
	for(ll i = 0; i <= n; i++) {
		ll num = i * a + (n - i) * b;
		if(judge(num)) {
			ans = (ans + C(n, i)) % mod;
		}
	}
	cout << ans;
	return 0;
}
posted @ 2021-10-22 20:26  脂环  阅读(72)  评论(0编辑  收藏  举报