题目地址
这道题关键在于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();
}