20180530模拟赛T2——绀碧之棺

Posted pfy_pfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20180530模拟赛T2——绀碧之棺相关的知识,希望对你有一定的参考价值。

题目背景Background

qiancl 得到了一张藏宝图,上面写了一道谜题。

题目描述 Description

定义\(F(n)\)为 n 在十进制下各个数位的平方和,求区间\([a,b]\)中有多少\(n\)满足\(k\times F(n) = n\)

输入描述 (coffin.in) Input Description

一行三个正整数\(k,a,b\)

输出描述 (coffin.out) Output Description

一行一个整数表示满足条件的\(n\)的个数。

样例输入Sample Input

51 5000 10000

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

测试数据 对应数据范围
其中12个测试点 \(1\le k,a,b\le 105\)
其中6个测试点 \(233\le k\le 250\),且\(1\le a,b\le10^8\)
剩下32个测试点 \(1\le k,a,b\le 10^{18}\)

样例中满足的\(3\)\(n\)分别是\(7293,7854,7905\)

题解

开始被\(10^{18}\)的数据范围给吓到了,%你赛结束后听说有人打了数位dp(代码看这里)。orz

然而正解是枚举??。

开始我没想那么多,就打了个普通的枚举,然后开始考虑优化。

首先,不难发现\(k\mid n\),于是我们就可以让\(n\) k个k个地加。

然后我们就考虑一下缩小枚举区间:

首先\(n\)是要求的,无法考虑在此方向拓展;

\(k\)于是我们就想到\(F(n)\),考虑到\(n \le 10^{18}\),又因为题目中明确说明“在十进制下”,于是我们就不难发现\(F(n)\le 9^2\times 18 = 1458\)(每一位都取\(9\))。又因为我们是\(k\)\(k\)位枚举的,所以我们最多只需枚举\(1458\)次。

注意开long long

代码

#include <fstream>
#include <algorithm>

using namespace std;

ifstream fin("coffin.in");
ofstream fout("coffin.out");

typedef long long LL;

LL a, b, k;

const int sqr[] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81};
const int kk = 81*18;

inline LL F(LL x)
{
    LL ans = 0;
    while(x)
    {
        ans += sqr[x%10];
        x /= 10;
    }
    return ans;
}

inline bool check(LL n)
{
    return F(n)*k == n;
}

int main()
{
    int ans = 0;
    fin >> k >> a >> b;
    if(a == b)
    {
        fout << check(a);
        return 0;
    }
    LL l = (a%k) ? ((a/k)+1)*k : a;
    LL r = min((kk*k), b);
    for(LL i = l; i <= r; i += k)
        if(check(i))
            ans++;
    fout << ans << '\n';
    return 0;
}

以上是关于20180530模拟赛T2——绀碧之棺的主要内容,如果未能解决你的问题,请参考以下文章

css Eflex-20180530的简单CSS

20180530

20180530_《Javascript获取网页大,元素位置(摘)》

20180530早课记录-Linux

2017/9/3模拟赛T2

11.12 模拟赛T2 冒泡排序图