[Daimayuan]完美数(C++,数学)

对于给定的数字 a a a , b b b ,当整数 n n n 在十进制下的所有数位都为 a a a b b b 时,我们称 n n n 是“好数”

对于好数 n n n ,当 n n n 在十进制下每一位的数字之和也为“好数”时,我们称 n n n 是一个“完美数”

请你求出有多少 m m m 位数是“完美数”

输入格式

输入一行三个整数 a a a , b b b , m m m , 含义如题面所示 ( 1 ≤ m ≤ 1 0 6 1≤m≤10^6 1m106, 1 ≤ a , b ≤ 9 1≤a,b≤9 1a,b9)。

输出格式

输出一行一个整数表示完美数的数量 , 由于答案可能很大 , 请你将答案对 1 0 9 + 7 10^9+7 109+7 取模

样例输入

5 1 5

样例输出

1

样例解释

只有 11111 11111 11111 满足要求

解题思路

一个长度为 m m m的数字,每个数字上的数只有两种可能

f o r for for循环枚举 a a a的数量 i i i,计算 a ∗ i + b ∗ ( m − i ) a*i+b*(m-i) ai+b(mi)是否为好数,以此方法找出所有完美数

如果符合条件,我们的计算公式为 C m i C_m^i Cmi

由于含有阶乘的计算,很容易爆精度,所以我们想要取模

但是要知道,取模运算对于除法是不成立的

于是,我们引入逆元

首先是逆元的定义:在 m o d   p mod\ p mod p的意义下,有 ( a ∗ b )   m o d   p ≡ 1 (a*b)\ mod\ p\equiv1 (ab) mod p1,我们称 b b b a a a的乘法逆元

逆元有这样一个性质: a / b   m o d   p = a ∗ i n v ( b )   m o d   p a/b\ mod\ p=a*inv(b)\ mod\ p a/b mod p=ainv(b) mod p i n v ( b ) inv(b) inv(b) b b b的乘法逆元)

也就是说,逆元可以将 m o d   p mod\ p mod p意义下的除法转化为乘法,然后我们就可以进行取模运算了

最后,AC代码如下

#include 
using namespace std;
const int max_m = 1e6;
const int mod_num = 1e9 + 7;

int a, b, m;
long long factorial[max_m + 1];

bool judge(int sum) {
	int t = 0;
	while (sum) {
		t = sum % 10;
		sum /= 10;
		if (!(t == a || t == b)) return false;
	}
	return true;
}

long long pow(long long x, long long y, long long p) {//快速幂
	long long ret = 1;
	while (y) {
		if (y & 1) ret = ret * x % p;
		x = x * x % p;
		y >>= 1;
	}
	return ret;
}

long long inv(long long x, long long p) {//求解mod p意义下,x的逆元
	return pow(x, p - 2, p);
}

long long cmp(long long m, long long n) {
	return factorial[n] * inv(factorial[m], mod_num) % mod_num * inv(factorial[n - m], mod_num) % mod_num;
}

int main() {
	factorial[0] = 1;
	for (int i = 1; i <= max_m; i++)
		factorial[i] = (factorial[i - 1] * i) % mod_num;

	cin >> a >> b >> m;
	long long ans = 0;
	for (int i = 0; i <= m; i++) {
		int sum = a * i + b * (m - i);
		if (judge(sum)) ans = (ans + cmp(i, m)) % mod_num;
	}
	cout << ans << endl;
	return 0;
}

你可能感兴趣的:(数学,c++,算法,组合数,逆元)