Project Euler 44 Sub-string divisibility( 二分 )


题意:五边形数由公式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\n",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\n", ans);
    return 0;
}
posted @ 2017-06-27 11:42  ojnQ  阅读(197)  评论(0编辑  收藏  举报