045题:
题意:
三角形数、五边形数和六角形数分别由以下公式给出:
三角形数 | Tn=n(n+1)/2 | 1, 3, 6, 10, 15, … |
五边形数 | Pn=n(3n−1)/2 | 1, 5, 12, 22, 35, … |
六边形数 | Hn=n(2n−1) | 1, 6, 15, 28, 45, … |
可以验证,T285 = P165 = H143 = 40755。
找出下一个同时是三角形数、五边形数和六角形数的数
思路:
由于六边形增长速度最快,所以我们优先根据公式遍历六边形数。然后我们看一下三角形数,把n = 2k - 1带入公式,得到Tk = k(2k - 1),所以,每下角标为2n - 1的三角形数都是六边形数,也就是说是六边形数,一定也是三角形数
因此我们只需要判断六边形数是否为五边形数即可,找到第一个就返回
有以下三个想法判断是否为五边形数:
1.先预处理出前10000个五边形数(应该不会超过这些),然后利用map<long long, bool>zcy映射一下这些五边形数,然后从144开始遍历六边形数,只要zcy[六边形数]存在就直接输出,时间复杂度O(m + n),其中m为预处理的五边形数的个数
2.外层for循环从144开始遍历六边形数,然后利用二分五边形数下角标查找是否存在对应的五边形数,若存在则返回并输出,时间复杂度O(n * logn)
3.for循环从144开始遍历六边形数,设得到的数设为t,我们求n(3n−1)/2 = t 的正整数解,也就是n = (1 + sqrt(1 + 24t)) / 6,若n为正整数则该数也为五边形数,时间复杂度O(n)
代码:
老规矩上时间复杂度最低的:
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <inttypes.h>
#include <map>
#include <algorithm>
#define ll int64_t
#define d int32_t
#define f double
#define r return
#define mem(a) memset(a, 0, sizeof(a));
using namespace std;
//六边形公式
ll g(ll a) {
r a * (2 * a - 1);
}
//判断该六边形数g(a)是否为五边形数
bool chooes(ll a) {
ll t = g(a);
f inx = (sqrt(24 * t + 1) + 1 ) / 6;
if (inx == (ll)inx) return true;
r false;
}
d main () {
for (ll i = 144; ; i++) {
if (chooes(i)) {
printf("%" PRId64"\n", g(i));
break;
}
}
r 0;
}
最后答案为:1533776805
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢