本文已参与[新人创作礼]活动,一起开启掘金创作之路
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
这是3月31日代码源div1的每日一题。
知识点:逆元
完美数 - 题目 - Daimayuan Online Judge
对于给定的数字 a , b ,当整数 n 在十进制下的所有数位都为 a 或 b 时,我们称 n 是“好数”
对于好数 n ,当 n在十进制下每一位的数字之和也为“好数”时,我们称 n 是一个“完美数”
请你求出有多少 m 位数是“完美数”
输入格式
输入一行三个整数 a , b , m , 含义如题面所示 (1≤m≤10^6,1≤a,b≤9)。
输出格式
输出一行一个整数表示完美数的数量 , 由于答案可能很大 , 请你将答案对 10^9+7 取模
样例输入
5 1 5
样例输出
1
样例解释
只有 11111 满足要求
问题解析
这题要求是,找出m位数的完美数。注意是m位数,比如5位数那就是10w,这里m最多可以取到10^6,这是相当吓人的,所以说也不用想着通过枚举来判断每一位是不是a或b了。但是我们完全可以反过来,既然好数是只有a和b的是数,那我们就用a和b排列出m位数,那他就是好数了。但完美数怎么办呢,一样的想法,完美数是好数各位数加起来仍然是好数,这里好数只有a和b组成,那么各位数之和就是x个a+y个b。我们只要枚举a或b的个数(x或y),然后计算出x*a+y *b,再看这个和是否是好数即可。如果是好数,那么说明x个a和y个b组成的m位数就将是个完美数。然后只要计算出他们的排列组合即可。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int MOD = 1e9 + 7, N = 1e6 + 10;
ll fact[N], infact[N];
ll qmi(int a, int b)
{
ll res = 1;
while (b)
{
if (b & 1) res = res * a % MOD;
a = a * (ll)a % MOD;
b >>= 1;
}
return res;
}
void init()
{
fact[0] = infact[0] = 1;
for (int i = 1; i < N; i++)
fact[i] = fact[i - 1] * i % MOD;
infact[N - 1] = qmi(fact[N - 1], MOD - 2);
for (int i = N - 2; i; i--)
infact[i] = infact[i + 1] * (i + 1) % MOD;
}
int C(int a, int b)
{
return (fact[a] * infact[b] % MOD * infact[a - b] % MOD) % MOD;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int a, b, m;
cin >> a >> b >> m;
init();
char c = a + '0', d = b + '0';
int x;
ll res = 0;
for (int i = 0; i <= m; i++)
{
x = m - i;
ll num = x * a + i * b;
bool flag = true;
while (num)
{
if (num % 10 != a && num % 10 != b)
{
flag = false;
break;
}
num /= 10;
}
if (!flag)continue;
res = (res + C(m,i)) % MOD;
}
cout << (res%MOD) << endl;
return 0;
}