代码源:669、完美数

241 阅读2分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路 logo.png

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;
}