CF1718D. Many Perfect Squares 题解 枚举

题目链接:https://codeforces.com/problemset/problem/1781/D

题目大意

给你一个长度为 n 的数列 a1,a2,,an

你需要在 [0,1018] 范围内找到一个整数 x,并将数列 a 中每个元素的数值都加上 x 得到一个新的数列 a1+x,a2+x,,an+x

你希望使新的数列中平方数的个数尽可能地多。

求:你能够得到的新数列中最多的平方数的个数。

题解

首先答案至少是 1

接着我们考虑能否得到至少 2 个数? 我们可以枚举 ij1i<jn),并找出 x 的哪些值 ai+xaj+x 都是完全平方数。

我们可以写出两个等式: ai+x=p2aj+x=q2 ,对于某个非负整数 p<q

我们将第一个等式减去第二个等式,并应用两个平方差的公式: ajai=q2p2=(qp)(q+p) 。可知, qpajai 的正的因数。

我们可以以 O(ajai) 的时间复杂度枚举 ajai 的所有因数。

对于每个这样的因数 d ,我们都可以得到一个简单的方程组,即 pq 的方程组,如下:

{qp=dq+p=ajaid

{p=12(ajaidd)q=12(ajaid+d)

如果 pq 都是整数,那就意味着我们找到了 x 的候选值: x=p2ai=q2aj .

对于 x 的每个候选值,我们只需计算它的平方和并找出最大值即可。

示例程序:

#include <bits/stdc++.h>
using namespace std;
#define int long long
int T, n, a[55];

// 判断整数 a 是不是平方数
bool check(int a) {
    int b = sqrt(a);
    return b * b == a;
}

int cal() {
    int res = 1; // 至少能得到一个平方数
    for (int i = 1; i < n; i++) {
        for (int j = i+1; j <= n; j++) {
            int num = a[j] - a[i];
            for (int d = 1; d * d <= num; d++) {
                if (num % d || num / d % 2 != d % 2)
                    continue;
                int p = (num / d - d) / 2;
                int q = (num / d + d) / 2;
                assert(p * p - a[i] == q * q - a[j]);
                int x = p * p - a[i];
                if (x < 0)  // x 在 [0, 1e18] 范围内
                    continue;
                int cnt = 0;
                for (int k = 1; k <= n; k++)
                    if (check(a[k] + x))
                        cnt++;
//                cout << "x = " << x << ", cnt = " << cnt << endl;
                res = max(res, cnt);
            }
        }
    }
    return res;
}

signed main() {
    cin >> T;
    while (T--) {
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        cout << cal() << endl;
    }
    return 0;
}
posted @   quanjun  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2020-10-14 洛谷P1967 货车运输 题解 最大生成树+LCA
点击右上角即可分享
微信分享提示