HDU - 5936[中途相遇法]

该博客介绍了如何运用中途相遇法解决HDU 5936题目,通过将y的范围缩小到1e5,枚举前半部分并结合二分搜索确定后半部分的匹配数。当x为0时需考虑特殊情况,由于y为正整数,此时结果应减1。
摘要由CSDN通过智能技术生成

题目地址
这道题关键在于f(y, k)-y可以拆成f(a, k) + f(b, k) -(a1e5+b)
我们就把y的1e9范围降到了1e5
然后我们可以对前一半1e5个数枚举出x-f(a, k) + a
1e5
然后对于后一半1e5个数用二分找到有多少和f(b, k)-b相同的就是个数。
注意当x等于零的时候会有a=0,b=0的情况,这时候我们要res-1因为题面说了y是正整数。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f[100005][12];
ll P(int x, int y) {
	ll res = 0;
	while(x) {
		ll t = 1, p = x%10;
		x /= 10;
		for(ll i = 1; i <= y; i++) {
			t *= p;
		}
		res += t;
	}
	return res;
}
ll val[100005];
void init() {
	for(int i = 0; i < 1e5; i++) {
		for(int j = 1; j <= 9; j++) {
			f[i][j] = P(i, j);
		}
	}
}
ll cal(ll x, ll k) {
	ll up = 1e5;
	for(ll i = 0; i < up; i++) {
		val[i] = f[i][k] - i*up;
	}
	ll res = 0;
	sort(val, val+up);
	for(int i = 0; i < up; i++) {
		ll t = f[i][k]-i;
		res += upper_bound(val, val+up, x-t) - lower_bound(val, val+up, x-t);
	}
	return res-(x==0);
}
int T = 0;
ll x, k;
void solve() {
	scanf("%lld%lld", &x, &k);
	printf("Case #%d: %lld\n", ++T, cal(x, k));
}
int main() {
	int Case;
	init();
	scanf("%d", &Case);
	while(Case--) solve();
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值