题目链接: 没有, 很迷
题目描述: 给你一个n , 让你求出一个最小的大于等于n的数 x , x满足 x * (x + 1) / 2 是完全平方
解题思路: 一开始我以为这个是一道水题, 就直接打的表, 后来看到n <= 1e16 ..... 蒙了, 既然x * (x+1)/ 2 是完全平方, 那么有两种可能, 其中一种可能就是x 是完全平方, (x+1) / 2 是完全平方, 另外一种可能就是 x / 2 是完全平方, x + 1 是 完全平方。 那么我们就可以设其中一个是k^2 另一个是(k+c)^2 , 举例来说第一个n = (k+c) ^ 2, (n+1) / 2 = k^2 所以
(k+c) ^ 2 + 1 = k ^ 2 现在我们想得到两个整数解 k , c ...... 现在我们解方程, k = c + √2*c^2¯+‾1‾, ( 原谅我这个根号如此的残缺不全........ TAT) 另一个是根号里的加一变成减1, 所以我们现在只需要枚举整数C, 使得K是整数就可以了, 现在我们考虑一下范围: n 最大是 1e16 , 所以 我们假设最坏情况就是说x 也是 1e16则 k 就是 1e8 , 而且我们从等式中看到 c 和 K就是一个数量级的, 所以c 也是 1e8, 时间限制是两秒钟, bingo !!!!!!
代码:
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <map> #include <set> #include <queue> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define mem0(a) memset(a,0,sizeof(a)) #define sca(x) scanf("%d",&x) #define de printf("======= ") typedef long long ll; using namespace std; const ll t = 1e8; ll ans[100]; void build() { int cnt = 0; for( ll i = 0; i <= t; i++ ) { ll t1 = 2*i*i + 1; ll t2 = 2*i*i - 1; ll t3 = sqrt(t1); ll t4 = sqrt(t2); if( t3 * t3 == t1 ) { ll k = i + t3; ans[cnt++] = 2*k*k-1; } if( t4 * t4 == t2 ) { ll k = i + t4; ans[cnt++] = 2*k*k; } } } int main() { build(); int t; sca(t); int cases = 1; ll n; while( t-- ) { scanf( "%lld", &n ); printf( "Case %d: %lld ", cases++, (ll)(*lower_bound(ans, ans+23, n)) ); } return 0; }
思考: 这道题先不说啥, 想的时间也太长了一点儿了吧, 自己做数论题虽然说不上多, 但是也不少了吧......为啥还是这么慢自己是不是应该做一下反思, 是不是因为自己平时做数论题的时候, 稍微简单的能想到, 稍微难一点儿的, 自己想了半个小时就去翻题解了, 那么自己是不是应该更加专心一点儿, 然后去多想一段时间? 虽然这样会比较痛苦吧, 但是可能这样自己以后会变的聪明一点儿吧, 然后, 尼玛面试的总结为啥你还是不写啊, 你是不是拖延症啊.....