AtCoder420 G

\(\color{black}{题目传送门}\)

题面

给你一个数字 \(X\),要你求出所有\(n\) 满足:\(\sqrt{n^2+n+X}\)是整数。并将所有满足要求的 \(n\) 从小到大排序后输出。

$-10^{14} \leq X \leq 10^{14} $

思路

首先\(\sqrt{n^2+n+X}\)是整数,就相当于\(n^2+n+X\)是平方数

分开讨论 \(X\) 为正数和为负数的情况

\(X\) 为正数

观察样例得到:\(n\)的负数解 \(=\) (\(-\)每个正数解) - 1

\(X\) 为正数,那么 \(n^2+n+X\) 显然是 $ > n^2$ 的一个平方数,为 $(n+k)^2 $ (\(k\)为正整数),

而 $(n+k)^2 = n^2 + 2nk + k^2 $
那么 \(X = (n^2 + 2nk + k^2) - (n^2 + n) = n \times (2k-1) + k^2\)
那么 \(n = \frac{(X - k^2)}{(2k-1)}\)

显然 \(1 \leq k^2 \leq X\) ,所以我们在\(\sqrt{X}\)的时间复杂度内可以枚举所有的 \(k\),对于每一个\(k\),如果 \(\frac{(X - k^2)}{(2k-1)}\) 不是非负整数,那么这个\(k\)不成立(\(n\)没有整数解),否则的话\(\frac{(X - k^2)}{(2k-1)}\)就是其中一个非负整数解,然后负数解就是(\(-\) 每个非负整数解) - 1

代码:

        vector<long long> v; // 用于存储非负数解
        for (int i = 1; 1ll * i * i <= x; i++) // 枚举k(我用的是i)注意:i*i 可能会爆int
        {
            double t = x - 1ll * i * i; // 先存一下
            t /= (i * 2 - 1); // 得到 n
            if (t == (long long)t) // 是整数
            {
                v.push_back(t); // 是个合法的非负整数解
            }
        }
        cout << v.size() * 2 << endl; // 每一个非负整数解都有对应的负数解
		// 由于x相同,所以:k越小,n越大,那么绝对值就越大。
        for (long long i : v)
        {
            cout << (-i) - 1 << ' ';  // 按照规律 输出负数解
        }
        reverse(v.begin(), v.end()); // 由于x相同,所以:k越小,n越大,因此我们需要大小转换一下。
        for (long long i : v)
        {
            cout << i << ' ';  // 输出正数解
        }
        cout << endl;

\(X\) 为负数

观察样例得到:\(n\)的负数解 \(=\) (\(-\)每个正数解) - \(1\) (和 \(X\)为正数一样)

为了方便,下文的\(X\)为输入的\(X\)的绝对值(算式的+-也会相应改)

首先由于\((n+1)^2 - n^2 = (n^2 + 2n + 1) - n^2 = 2n + 1\)\(n - X\)显然小于 \(2n + 1\)所以 \((n^2+n-X)\)一定小于 \((n+1)^2\)

所以 \(n^2+n-X = (n-k)^2\) ( \(k\)为非负整数 )

而 $(n-k)^2 = n^2 - 2nk + k^2 $
那么 \(X = (n^2 + n) - (n^2 - 2nk + k^2) - (n^2 + n) = n \times (2k + 1) - k^2\)
那么 \(n = \frac{(X + k^2)}{(2k+1)}\)

显然 \(0 \leq k^2 \leq X\) ,所以我们在\(\sqrt{X}\)的时间复杂度内可以枚举所有的 \(k\),对于每一个\(k\),如果 \(\frac{(X + k^2)}{(2k+1)}\) 不是非负整数,那么这个\(k\)不成立(\(n\)没有整数解),否则的话\(\frac{(X + k^2)}{(2k+1)}\)就是其中一个非负整数解,然后负数解就是(\(-\) 每个非负整数解) - 1

代码:

        vector<long long> v; // 暂存非负整数解
        x = -x; // 负改正
        for (int i = 0; 1ll * i * i <= x; i++) // 枚举k(我用的i)注意从0开始枚举而非从1开始。因为n^2+n-X可以等于n^2
        {
            double t = x + 1ll * i * i; // 先存一下 X+k^2
            t /= (i * 2 + 1); // 除以i*2+1
            if (t == (long long)t) // t是整数解
            {
                v.push_back(t); // 存下这个非负整数解
            }
        }
		// 输出部分同 X为正数
        cout << v.size() * 2 << endl; 
        for (long long i : v)
        {
            cout << (-i) - 1 << ' '; 
        }
        reverse(v.begin(), v.end());
        for (long long i : v)
        {
            cout << i << ' ';
        }
        cout << endl;

\(X = 0\)

直接输出即可,但是不要忘记特判他。

        if (x == 0)
        {
            cout << 2 << endl << "-1 0 " <<endl; //  注意还有一个-1
            return 0;
        }

总代码:

高清代码附上:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    long long x;
    cin >> x;
	// x非负
    if (x >= 0)
    {
	    // x = 0
        if (x == 0)
        {
            cout << 2 << endl << "-1 0 " <<endl;
            return 0;
        }
		// x为正数
        vector<long long> v;
        for (int i = 1; 1ll * i * i <= x; i++)
        {
            double t = x - 1ll * i * i;
            t /= (i * 2 - 1);
            if (t == (long long)t)
            {
                v.push_back(t);
            }
        }
        cout << v.size() * 2 << endl;
        for (long long i : v)
        {
            cout << (-i) - 1 << ' ';
        }
        reverse(v.begin(), v.end());
        for (long long i : v)
        {
            cout << i << ' ';
        }
        cout << endl;
    }
    else // X为负数
    {

        vector<long long> v;
        x = -x;
        for (int i = 0; 1ll * i * i <= x; i++)
        {
            double t = x + 1ll * i * i;
            t /= (i * 2 + 1);
            if (t == (long long)t)
            {
                v.push_back(t);
            }
        }
        cout << v.size() * 2 << endl;
        for (long long i : v)
        {
            cout << (-i) - 1 << ' ';
        }
        reverse(v.begin(), v.end());
        for (long long i : v)
        {
            cout << i << ' ';
        }
        cout << endl;
    }
    return 0;
}

完结撒花★,°:/$:.°★

点个赞吧!

posted @ 2025-08-25 22:11  MichaelZeng  阅读(8)  评论(0)    收藏  举报