链接
http://acm.hdu.edu.cn/showproblem.php?pid=5936
题解
如果一个数是
11
11
11位数,那么各位数字之和最大是
11
×
9
9
=
4261625379
11\times 9^9=4261625379
11×99=4261625379,而最小的
11
11
11位数是
100000000000
100000000000
100000000000,
4261625379
−
100000000000
=
−
95738374621
<
0
4261625379-100000000000=-95738374621<0
4261625379−100000000000=−95738374621<0,题目说了
x
≥
0
x\geq 0
x≥0,所以
y
y
y不可能超过
10
10
10位
那么把整个数字拆成前
5
5
5位和后
5
5
5位来做,后
5
5
5位的
f
(
y
,
k
)
−
y
f(y,k)-y
f(y,k)−y预处理成一张表,然后枚举前
5
5
5位
x
x
x,看下
x
−
(
f
(
x
,
k
)
−
x
×
100000
)
x-(f(x,k)-x\times 100000)
x−(f(x,k)−x×100000)在表中出现了多少次就行了
一开始用
m
a
p
map
map超时,后来换成二分查找就过了…果然
m
a
p
map
map自带大常数
注意
x
=
0
x=0
x=0的情况,因为题目一上来就说了
y
y
y是正数,所以不能把
0
0
0也给算上
代码
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
typedef long long ll;
ll p[10][10], s[10][maxn], a[maxn], b[maxn], lis[maxn];
int main()
{
ll i, j, k, T, kase, X, K, ans;
for(i=0;i<=9;i++)for(j=0;j<=9;j++)
{
p[i][j]=1;
for(k=1;k<=j;k++)p[i][j]*=i;
}
for(k=1;k<=9;k++)
for(i=0;i<=99999;i++)
{
ll x=i;
while(x)
{
s[k][i]+=p[x%10][k];
x/=10;
}
}
cin>>T;
for(kase=1;kase<=T;kase++)
{
cin>>X>>K;
for(i=0;i<=99999;i++)
{
a[i]=s[K][i]-i*100000;
b[i]=s[K][i]-i;
}
ans=0;
sort(b,b+100000);
for(i=0;i<=99999;i++)
{
ll t=X-a[i];
ans += upper_bound(b,b+100000,t) - lower_bound(b,b+100000,t);
}
if(X==0)ans--;
cout<<"Case #"<<kase<<": "<<ans<<endl;
ans=0;
}
return 0;
}