urumqi 网络赛 E Half-consecutive Numbers 数论

  题目链接: 没有, 很迷

  题目描述: 给你一个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;
}
View Code

  思考: 这道题先不说啥, 想的时间也太长了一点儿了吧, 自己做数论题虽然说不上多, 但是也不少了吧......为啥还是这么慢自己是不是应该做一下反思, 是不是因为自己平时做数论题的时候, 稍微简单的能想到,  稍微难一点儿的, 自己想了半个小时就去翻题解了, 那么自己是不是应该更加专心一点儿, 然后去多想一段时间? 虽然这样会比较痛苦吧, 但是可能这样自己以后会变的聪明一点儿吧, 然后, 尼玛面试的总结为啥你还是不写啊, 你是不是拖延症啊.....

原文地址:https://www.cnblogs.com/FriskyPuppy/p/7499538.html