因为K只有10,如果x为999999999,F(x,k)也就才9^10,所以y的最大值不会很大,预计10^10,所以把这10位数,折半枚举一下,预处理左边5位,然后再枚举右边5位,这样时间复杂度就只会有n*logn(n=100000);问题得到解决。
至于x==0为什么要-1?
x = f(y,k) - y >= 0
-> f(y,k) >= y
-> y > 0
-> x > f(y,k) >= y
所以y的长度不超过10位
y = a + b*(1e5)
x = f(a,k) - a + f(b,k) - b*(1e5)
x - f(a,k) + a = f(b,k) - b*(1e5)
那f(b,k) - b*(1e5) == (x - f(a,k) + a)的数量和就是答案
预处理出所有的 f(b,k) - b*(1e5)
枚举a,二分法找出满足f(b,k) - b*(1e5) == (x - f(a,k) + a)的数量和即可
当x==0时,因为y>0,a,b不能同时为0,所以答案要-1
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
ll f[12][12];
ll a[100010];
ll cnt[12][100010];
vector<ll>g[12];
ll solve(ll num,ll k)
{
ll ans=0;
while(num)
{
ans+=f[num%10][k];
num/=10;
}
return ans;
}
void init()
{
for(int i=0;i<=9;i++)
{
f[i][1]=i;
for(int j=2;j<=9;j++)
f[i][j]=f[i][j-1]*i;
}
for(int i=1;i<=9;i++)
{
for(ll num=0;num<100000;num++)
{
a[num]=solve(num,i)-num*100000;
}
sort(a,a+100000);
int t=0;
int xx=-1;
while(t<100000)
{
if(t==0||a[t]!=a[t-1])
{
g[i].push_back(a[t]);
cnt[i][++xx]++;
}
else
{
cnt[i][xx]++;
}
t++;
}
}
}
int main()
{
init();
int t;scanf("%d",&t);
for(int v=1;v<=t;v++)
{
ll x,k;scanf("%lld%lld",&x,&k);
ll ans=0;
for(int i=0;i<100000;i++)
{
ll v=solve(i,k)-i;
ll need=x-v;
int pos=lower_bound(g[k].begin(),g[k].end(),need)-g[k].begin();
if(pos<g[k].size()&&pos>=0&&g[k][pos]==need)
{
ans+=cnt[k][pos];
}
}
if(x==0)
ans--;
printf("Case #%d: %lld\n",v,ans);
}
return 0;
}