题意:五边形数由公式Pn=n(3n−1)/2生成,在所有和差均为五边形数的五边形数对Pj和Pk中,找出使D = |Pk − Pj|最小的一对;此时D的值是多少?
思路:二分找和差
/*************************************************************************
> File Name: euler044.c
> Author: WArobot
> Blog: http://www.cnblogs.com/WArobot/
> Created Time: 2017年06月27日 星期二 10时59分39秒
************************************************************************/
#include <stdio.h>
#include <inttypes.h>
#define MAX_N 5000
#define MAX_RANGE 37497500
bool Binary_Serch(int32_t n , int32_t *p) { // 判断n是否在数组num[]中
if (n > MAX_RANGE) return false;
int32_t l = 1 , r = MAX_N - 1 , mid;
while (l < r) {
mid = (l + r) >> 1;
if (p[mid] < n) l = mid + 1;
else r = mid;
}
return p[r] == n;
}
int32_t main() {
int32_t p[MAX_N];
for (int32_t i = 1 ; i < MAX_N ; i++) {
p[i] = ( 3 * i * i - i ) / 2;
}
int32_t ans = MAX_RANGE + 10;
bool flag = false;
for (int32_t k = 1 ; k < MAX_N ; k++) { // p[k] > p[j] k 从小到大枚举 j 从大到小枚举
for (int32_t j = k - 1 ; j >= 1 ; j--) {
if (!Binary_Serch(p[k] + p[j] , p)) continue;
if (!Binary_Serch(p[k] - p[j] , p)) continue;
if (ans > p[k] - p[j]) { // 假如 ans已经被 p[k] - p[j] 更新完成那就没必要向下继续枚举j,因为向下枚举j时D肯定不会被更新
ans = p[k] - p[j]; flag = true;
break;
}
}
if (flag) break; // 如果 ans已经被更小的 p[k] - p[j] 更新过一次,那就没有必要继续枚举k了,因为向上继续枚举k并不会让D更小
}
printf("%d
",ans);
return 0;
}
方法二:
/*************************************************************************
> File Name: test.cpp
> Author:
> Mail:
> Created Time: 2018年02月03日 星期六 08时42分28秒
************************************************************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll Pentagonal(ll n) {
return n * (n * 3 - 1) / 2;
}
bool isPentagonal(ll n) {
int l = 1, r = n, mid;
while (l <= r) {
mid = (l + r) >> 1;
ll t = Pentagonal(mid);
if (t == n) {
return true;
} else if (t < n) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return false;
}
int main() {
ll ans = INT_MAX;
ll n = 1, m, p1, p2;
while (true) {
p1 = Pentagonal(n);
p2 = Pentagonal(n - 1);
if (p1 - p2 > ans) break;
for (int m = n - 1 ; m >= 1 ; --m) {
p2 = Pentagonal(m);
if (p1 - p2 >= ans) break;
if (isPentagonal(p1 + p2) && isPentagonal(p1 - p2)) {
ans = p1 - p2;
}
}
++n;
}
printf("ans is %lld
", ans);
return 0;
}