题意:
f(y,K)=∑z in every digits of yzK
x=f(y,K)−y ,给出x,k,求出满足这个等式的y有多少个。
思路:易得y最大为10^10,而y 可以分成两部分,y = y1 * 100000 + y2,y1,y2 <10^5;
等式等效为: x = f(y1,k) - y1 * 100000 + f(y2,k) - y2 ;我们可以预处理出前一部分的值,并打好表;然后枚举后一部分的值,进行二分查找与他相加等于x的值,加上它的个数,复杂度为100000*log(100000);
注意当x == 0的时候要减一。
PS :比赛的时候想不到解体思路,还有特判x== 0的操作。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 10;
typedef long long ll;
ll p[11][11];
ll fun(ll n,ll k)
{
ll ret = 0;
while(n)
{
ret += p[n % 10][k];
n /= 10;
}
return ret;
}
vector<ll>g[11];
ll a[maxn];
ll cnt[11][maxn];
void Init()
{
for(ll i = 1; i <= 9; i ++)
{
ll temp = i;
for(ll j = 1; j <= 9; j ++)
{
p[i][j] = temp;temp *= i;
}
}
for(ll i = 1; i <= 9; i ++)
{
for(ll j = 0; j < maxn; j ++)
{
a[j] = fun(j,i) - j * 100000;
}
sort(a,a + maxn);
ll x = 0,y = -1;
while(x < maxn)
{
if(x == 0 || a[x] != a[x - 1])
{
y ++;
g[i].push_back(a[x]);
cnt[i][y] = 1;
}
else cnt[i][y] ++;
x ++;
}
}
}
int main()
{
Init();
ll Tcase;
scanf("%I64d",&Tcase);
for(ll ii = 1; ii <= Tcase; ii ++)
{
ll x;ll k;
scanf("%I64d%I64d",&x,&k);
ll ans = 0;
for(ll i = 0; i < maxn; i ++)
{
ll t = fun(i,k);
ll temp = x - (t - i);
ll pos = lower_bound(g[k].begin(),g[k].end(),temp) - g[k].begin();
if(pos < g[k].size() && pos >= 0 && g[k][pos] == temp)
{
ans += cnt[k][pos];
}
}
if(x == 0)
ans --;
printf("Case #%I64d: %I64d\n",ii,ans);
}
return 0;
}