- 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5936
- 题意:
- f ( y , k ) = ∑ z   i n   e v e r y   d i g i t s   o f   y Z k ( e . g . f ( 233 , 2 ) = 2 2 + 3 2 + 3 2 = 22 ) f(y, k) = \sum_{z\,in\,every\,digits\,of\,y} Z^{k} \quad(e.g.f(233,2) = 2^2 + 3^2 + 3^2 = 22) f(y,k)=zineverydigitsofy∑Zk(e.g.f(233,2)=22+32+32=22)
- x = f ( y , k ) − y ( 1 ) x=f(y,k)-y\quad(1) x=f(y,k)−y(1)已知 x 和 k ,求符合上式的 y 的个数
- 坑点:注意题中表明 y 为正数, 即 y>0
- 算法:折半枚举。手动模拟得y<=1e10, 令
y
=
a
+
b
∗
1
e
5
(
1
<
=
a
<
=
99999
,
0
<
=
b
<
=
100000
)
y = a + b*1e5\quad(1<=a<=99999, 0<=b<=100000)
y=a+b∗1e5(1<=a<=99999,0<=b<=100000)带入式(1)得
x
=
f
(
a
,
k
)
−
a
+
f
(
b
,
k
)
−
b
∗
1
e
5
x=f(a,k)-a+f(b,k)-b*1e5
x=f(a,k)−a+f(b,k)−b∗1e5即
x
−
f
(
a
,
k
)
+
a
=
f
(
b
,
k
)
−
b
∗
1
e
5
x-f(a,k)+a=f(b,k)-b*1e5
x−f(a,k)+a=f(b,k)−b∗1e5预处理b,枚举a,即可在限制复杂度内求出答案。
- 该算法减少了枚举 a 时,重复枚举 b 的运算量。
#include <bits/stdc++.h>
#define pi acos(-1);
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 150000 + 10;
const int mod = 1e9 + 7;
map<LL, LL> mp[15];
LL F(LL y, LL k)
{
LL tmp, ans=0, mul=1;
while(y){
tmp = y%10;
mul = 1;
for(LL i=1; i<=k; i++) mul *= tmp;
ans += mul;
y/=10;
}
return ans;
}
void init()
{
for(LL k=1; k<=9; k++){
for(LL i=0; i<100000; i++){
mp[k][F(i, k)-i*100000]++;
//if(F(i, k)-i*100000 == 0) printf("----%lld %lld\n", i, k);
}
}
}
int main()
{
init();
LL T, k, x, cas=0; scanf("%lld", &T);
while(T--){
scanf("%lld%lld", &x, &k);
LL ans = 0;
for(LL i=1; i<=99999; i++){
if(mp[k].count(x-F(i, k)+i)){
ans += mp[k][x-F(i, k)+i];
//printf("...%lld\n", i);
}
//if(mp[k][x-F(i,k)+i]) printf("...%d %d %lld %lld\n", i, k, x-F(i, k)+i, mp[k][x-F(i,k)+i]);
}
printf("Case #%lld: %lld\n", ++cas, ans);
}
}
/*
9
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
*/