题意:
给你x和k,问你有多少个y满足题上的两个公式
y的位数不会超过10位,因为如果超过十位的话f(y, k)-y一定是个负数
比如假设y是11位,那么f(y, k)最大值是9^9*11它只有10位
这样可以将y强行填到10位,比如y=236,那么就让y=0000000236
这样就不用判断位数了
之后暴力出前5位的所有情况(0-99999)
举个例子:假设当时是25436,k为6,那么当前值就是2^6+5^6+4^6+3^6+6^6-25436*100000
将算出来的100000个值存到L[]数组里排个序,注意每个k都要这样算一次
然后再暴力算出后5位的所有情况(0-99999)
和上面一样的:假设当时是25436,k为6,那么当前值就是2^6+5^6+4^6+3^6+6^6-25436
将算出来的100000个值存到R[]数组里排个序,每个k都要这样算一次仍然
O(nklog(n)) (n=100000)的复杂度预处理结束后
每次询问x, k相当于找到有多少组R[]+L[]==x,因为R和L都是有序,这样就可以O(n)计算了
总复杂度O(nklog(n)+Tn)
注意当x=0时答案要-1,因为y!=0
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define LL long long
LL L[12][100005], R[12][100005], cnt[12], p[12][12];
int main(void)
{
LL T, x, k, i, j, q, temp, sum, ans, cas = 1;
for(i=0;i<=9;i++)
{
p[i][1] = i;
for(j=2;j<=9;j++)
p[i][j] = p[i][j-1]*i;
}
for(k=1;k<=9;k++)
{
for(i=0;i<=99999;i++)
{
sum = 0;
temp = i;
for(j=1;j<=5;j++)
{
sum += p[temp%10][k];
temp /= 10;
}
L[k][++cnt[k]] = sum-i*100000;
R[k][cnt[k]] = sum-i;
}
sort(L[k]+1, L[k]+cnt[k]+1);
sort(R[k]+1, R[k]+cnt[k]+1);
}
scanf("%lld", &T);
while(T--)
{
ans = 0;
scanf("%lld%lld", &x, &k);
q = cnt[k];
for(i=1;i<=cnt[k];i++)
{
if(i!=1 && R[k][i]==R[k][i-1])
{
ans += sum;
continue;
}
sum = 0;
if(q<=0) break;
while(R[k][i]+L[k][q]>x && q>=1) q--;
while(R[k][i]+L[k][q]==x && q>=1) q--, sum++;
ans += sum;
}
if(x==0)
ans--;
printf("Case #%lld: %lld\n", cas++, ans);
}
return 0;
}