1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ...
It can be seen that P4 + P7 = 22 + 70 = 92 = P8. However, their difference, 70 − 22 = 48, is not pentagonal.
Find the pair of pentagonal numbers, Pj and Pk, for which their sum and difference are pentagonal and D = |Pk − Pj| is minimised; what is the value of D?
通过公式生成五角形数,P n = n(3 n -1)/ 2。前十个五角形数字是:
1,5,12,22,35,51,70,92,117,145,......
可以看出P 4 + P 7 = 22 + 70 = 92 = P 8。然而,他们的差,70 - 22 = 48,不是五角形数字。
找到一对五角形数,P j和P k,它们的和和差是五角形数,D = | P k - P j | 最小化; D的值是多少?
思路
1.二分法找五角形数字 同四十五题
2.动态边界:
(1)设j<k;d为最小的pena(k)-pena(j);
(2)内层循环枚举j时,若pena(k) - pena(j) > d,则没有再继续枚举j的意义;
(3)外层循环枚举k时,若pena(k)-pena(k-1) > d,则没有再继续枚举k的意义;
#include <stdio.h>
#include <inttypes.h>
static inline int64_t pena(int64_t x){
return x * (3 * x - 1) / 2;
}//在c语言中,用内联函数时一定要加static,不然将被当作符号处理并报错;
int is_pen(int64_t x){
int min = 1, max = x;
while(min <= max){
int64_t mid = (min + max) / 2;//每次mid值都要变换,所以应写在内层循环里面;
int64_t pen = pena(mid);
if(pen == x) return 1;
if(pen < x) min = mid + 1;
else max = mid - 1;
}
return 0;
}
int main(){
int64_t k = 2;
int64_t d = INT64_MAX;//int64_t的最大值;
while(pena(k) - pena(k - 1) < d){
int64_t j = k - 1;
while(pena(k) - pena(j) < d){
if(is_pen(pena(k) + pena(j)) && is_pen(pena(k) - pena(j))){
d = pena(k) - pena(j);
}
j--;
if(!j) break;//当j=0时,即便pena(k)-pena(j)也必须跳出循环,不然就是死循环;
}
k++;
}
printf("%"PRId64"\n", d);
return 0;
}