码迷,mamicode.com
首页 > 其他好文 > 详细

20180530模拟赛T2——绀碧之棺

时间:2018-05-30 21:35:57      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:https   rip   lob   .cpp   inpu   tps   const   return   turn   

题目背景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——绀碧之棺

标签:https   rip   lob   .cpp   inpu   tps   const   return   turn   

原文地址:https://www.cnblogs.com/pfypfy/p/9112841.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!