惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The GitHub Blog
The GitHub Blog
MyScale Blog
MyScale Blog
爱范儿
爱范儿
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
美团技术团队
Y
Y Combinator Blog
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
Martin Fowler
Martin Fowler
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
M
MIT News - Artificial intelligence
博客园 - Franky
V
Visual Studio Blog
I
InfoQ
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
博客园 - 司徒正美
L
LangChain Blog

OhYee 博客

小鹏辅助驾驶测评|OhYee 博客 小鹏非支持手机开启自动解锁|OhYee 博客 使用函数计算实现 301 重定向|OhYee 博客 针对 HTML 内容使用 Ant Design 图片弹框|OhYee 博客 博客进程泄露及僵尸进程解决|OhYee 博客 蓝易云服务器体验|OhYee 博客 SSH 调起本地 VSCode|OhYee 博客 【2022 秋招内推】阿里云后端研发工程师|OhYee 博客 使用函数计算获取 IP 地址信息|OhYee 博客 正确获取客户端 IP/HTTP Header 也可能重复|OhYee 博客 评测 Oculus Quest2 及 BigScreen|OhYee 博客 NextJS 热重载保留状态|OhYee 博客 如何优雅地贴 gist 代码|OhYee 博客 Linux 精细化文件权限|OhYee 博客 VSCode 容器开发环境|OhYee 博客 Clash 的不兼容更新排查|OhYee 博客 Zeek 导出 PCAP|OhYee 博客 记一次 ssh 配置问题|OhYee 博客 Git Commit 规范化工具|OhYee 博客 谈谈《星之卡比-探索发现》|OhYee 博客 VSCode 快捷键绑定 Shell 命令|OhYee 博客 ASN.1 语法及 X.509 证书格式解析解析|OhYee 博客 腾讯企业邮箱忽略 MX 记录发信|OhYee 博客 Chrome/Edge 标签组插件|OhYee 博客 【应届内推】阿里云后端研发工程师|OhYee 博客 损坏的 Typecho 备份处理为 JSON|OhYee 博客 VS Code VIM 插件高效使用|OhYee 博客 SSH 正反向代理|OhYee 博客 Let's Encrypt 根证书过期引发的问题|OhYee 博客 OpenWRT 忽略内核依赖|OhYee 博客
HDU 5936.Difference(2016 CCPC 杭州 D)|OhYee 博客
2016-11-21 · via OhYee 博客

题目

Description

Little Ruins is playing a number game, first he chooses two positive integers y and K and calculates f(y,K), here

f(y,K) = ∑in every digits of y zK (f(233,2) = 22+32+32=22)

then he gets the result

x=f(y,K)-y

As Ruins is forgetful, a few seconds later, he only remembers K, x and forgets y. please help him find how many y satisfy x=f(y,K)-y.

Input

First line contains an integer T, which indicates the number of test cases.

Every test case contains one line with two integers x, K.

Limits
1≤T≤100
0≤x≤109
1≤K≤9

Output

For every test case, you should output 'Case #x: y', where x indicates the case number and counts from 1 and y is the result.

Sample Input

2
2 2
3 2

Sample Output

Case #1: 1
Case #2: 2

题解

求所有满足 x=f(y,K)-y 的数量
计算一下,可以发现 y 最多为 10 位 (计算下极端情况)
而暴力搜索 10 位的数字显然会超时
可以采用 中途相遇法 的思路,将 10 位数字分成两个 5 位
然后分别计算两部分,再对两部分进行比较即可

首先可以知道, f(y,K) 函数是一个有确定的函数,因此可以打表直接查询结果
而每次需要求的 zK 也是有确切结果的,也可以打表(对于这道题,不打表时间会多很多)

x=f(y,K)-y 化成 x=f(a,K)+f(b,K)-a*100000-b 其中 a b 分别是 y 的前 5 位和后 5 位
可以看出, f(a,K)-a*100000f(b,K)-b 可以分别在自己的循环里计算

用一个数组来记录第一个循环能得到的结果,在第二个循环里累计其结果在第一个循环里的数量
(用 map 会超时,可以用 lower_bound()upper_bound() 快速求个数)

特别注意,如果 x=0 在两个循环会被重复计算 1 次,因此要额外 -1

代码量不大,思路也比较容易理解,注意各种打表优化即可

代码

//#include <ctime>
//#define debug

#include <cstdio>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

typedef long long LL;

LL List[100005][10];
LL Pre[100005];
int pw[10][10];

int Pow(int a,int n) {
    if(pw[a][n] == -1){
        if(n == 1) pw[a][n] = a;
        else if(n == 0) pw[a][n] = 1;
        else pw[a][n] = Pow(a,n / 2) * Pow(a,n - n / 2);
    }
    return pw[a][n];
}

inline LL f(LL y,int k) {
    // if(List[y][k] == -1) {
    //     LL sum = 0;
    //     while(y) {
    //         sum += Pow((int)(y % 10),k);
    //         y /= 10;
    //     }
    //     List[y][k] = sum;
    // }
    return List[y][k];
}

int lower_bound(LL *arr,int size, LL key) {
    int half;
    int mid;
    int first = 0;
    while (size > 0) {
        half = size >> 1;
        mid = first + half;
        if (arr[mid] < key) {
            first = mid + 1;
            size = size - half - 1;
        } else {
            size = half;
        }
    }
    return first;
}
int upper_bound(LL *arr,int size, LL key) {
    int mid;
    int first = 0;
    int half;
    while (size > 0) {
        half = size >> 1;
        mid = half + first;
        if (arr[mid] > key) {
            size = half;
        } else {
            first = mid + 1;
            size = size - half - 1;
        }
    }
    return first;
}

inline int Count(LL pre) {
    return upper_bound(Pre,100000,pre) - lower_bound(Pre,100000,pre);
}

int main() {
    #ifdef debug
    freopen("in.txt","r",stdin);
    int start = clock();
    #endif

    cin.tie(0);
    cin.sync_with_stdio(false);

    int T;
    cin >> T;
    //scanf("%d",&T);

    memset(pw,-1,sizeof(pw));

    for(int i=0;i<100000;i++){
        for(int j=1;j<=9;j++){
            LL sum = 0;
            int y = i;
            while(y) {
                sum += Pow((int)(y % 10),j);
                y /= 10;
            }
            List[i][j] = sum;
        }
    }
    //memset(List,-1,sizeof(List));

    for(int kase = 1;kase <= T;kase++) {
        LL x;
        int k;
        cin >> x >> k;
        //scanf("%d%d",&x,&k);

        //前5位的各位k次方 - 前五位数据
        for(int i = 0;i < 100000;i++) {
            LL pre = f(i,k) - (LL)i * 100000;
            Pre[i] = pre;
        }
        
        sort(Pre,Pre + 100000);
        LL cnt = 0;

        //后5位的各位k次方 - 后五位数据
        for(int i = 0;i < 100000;i++) {
            LL post = f(i,k) - (LL)i;
            LL pre = x - post;
            cnt += Count(pre);
        }
        cout << "Case #" << kase << ": " << cnt-(x==0) << endl;
       // printf("Case #%d: %d\n",kase,cnt);
    }

    #ifdef debug
    printf("Time:%.3lfs\n",double(clock() - start) / CLOCKS_PER_SEC);
    #endif

    return 0;
}