[HDOJ 4430] [2012 Asia Changchun Regional Contest K Problem] 解题报告
2012 Asia Changchun Regional Contest
K题 Yukan's Birthday
HDOJ 4430
知识点总结:
-
二分查找,时间复杂度: log(n)
-
整数的幂运算不要使用pow()函数,因为无法保证精度问题,通过【快速求幂】方法求解。
// 快速求幂 原理 a^n = a^(2*n/2) // 快速求幂 时间复杂度 log(n)
解题思路:
这道题是通过枚举+二分的方法解决的。
首先,通过等比数列求和公式我们可以得到r的最大值的范围:r_max < 40, 因此面对[1~40]范围的r可以进行穷举。
接下来, 最外圈的蜡烛个数 k ^ r < n, 所以我们可以进一步缩减k的范围,防止运算结果爆出long long,然后通过二分确定与r对应的k的值。
最后,选取r * k最小的组合即可。
代码:
https://github.com/HouJP/ACM_HDOJ/blob/master/hdoj_4430.cpp
/*************************************************************************
> File Name: 4430.cpp
> Author: HouJP
> Mail: peng_come_on@126.com
> Created Time: 五 8/ 8 10:03:50 2014
************************************************************************/
#include <cstdio>
#include <cstring>
#include <cmath>
#define LL long long
LL n, k;
int r;
LL fast_pow(LL a, int b) {
LL exp = 1;
while (b) {
if (b & 1) {
exp *= a;
}
a = a * a;
b >>= 1;
}
return exp;
}
LL binary_find(int r, LL k_max, LL n) {
LL k_l = 2, k_r = k_max, k_m, sum;
while (k_l <= k_r) {
k_m = (k_l + k_r) / 2;
sum = k_m * ( 1 - fast_pow(k_m, r)) / (1 - _m);
if (sum == n) {
return k_m;
} else if (sum > n) {
k_r = k_m - 1;
} else if (sum < n) {
k_l = k_m + 1;
}
}
return -1;
}
int main() {
while (~scanf("%lld", &n)) {
k = n - 1;
r = 1;
for (int i = 2; i < 40; ++i) {
LL kk;
LL k_max = (LL)pow(n, 1.0 / i);
kk = binary_find(i, k_max, n);
if (-1 != kk) {
if ((i * kk < r * k) || ((i * kk == r * k ) && (i < r))) {
r = i;
k = kk;
}
}
kk = binary_find(i, k_max, n - 1);
if (-1 != kk) {
if ((i * kk < r * k) || ((i * kk == r * k) && (i < r))) {
r = i;
k = kk;
}
}
}
printf("%d %lld\n", r, k);
}
return 0;
}

浙公网安备 33010602011771号