计蒜客 — 等差数列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lzyws739307453/article/details/83584625

https://nanti.jisuanke.com/t/26

  • 时间限制 2000ms
  • 空间限制 65536K

一个等差数列是一个能表示成 a, a+b, a+2b,..., a+nb (n=0,1,2,3,...的数列。

在这个问题中 a 是一个非负的整数,b 是正整数。写一个程序来找出在双平方数集合(双平方数集合是所有能表示成 p^2+q^2 的数的集合) S 中长度为 n 的等差数列。

输入格式

输入包括两行,第一行为 N(3≤N≤25)要找的等差数列的长度。第二行是找到的双平方数 pp 和 qq 的上界 M(0≤p,q≤M)。

输出格式

输出一行或者多行,如果没有找到数列,输出NONE。否则输出一个整数对a b(这些行应该先按 b 排序再按 a 排序)

样例输入

5
7

样例输出

1 4
37 4
2 8
29 8
1 12
5 12
13 12
17 12
5 20
2 24

解题思路

这个题目很简单,就是采用暴力求解,枚举所有可能的首项和公差,关键是通过剪枝,降低运行时间。

首先,我们用一个数组vis[i]记录i是否是双平方数;同时为了加速,用sq[]有序记录所有的双平方数(除去中间的空位置,对付大数据时很有用)。然后就很简单了,我们通过枚举首项和公差,并连续算N-1个数看是否都在数组vis[]中。

注意,要求按b排序,再按a二次排序。

提示:利用约束a+(n-1)*b <= sq[max]来剪枝。

#include <iostream>
#include <algorithm>
using namespace std;
int vis[150010], sq[150010];
struct node
{
    int a,b;
}s[150010];
int cmp(node x, node y)
{
    if (x.b != y.b)
        return x.b < y.b;
    return x.a < y.a;
}
int main()
{
    int a, ans, num, n, m, k;
    while (cin >> n >> m)
    {
        num = a = 0;
        for (int p = 0; p <= m; p++)
            for (int q = p; q <= m; q++)
                if (!vis[p * p + q * q])
                    vis[sq[a++] = p * p + q * q] = 1;
        for (int i = 0; i < a; i++)
        {
            for (int j = 1; j <= 2 * m * m; j++)
            {
                if (sq[i] + (n - 1) * j > 2 * m * m)
                    break;
                for (k = 1; k < n; k++)
                    if (!vis[sq[i] + k * j])
                        break;
                if (k != n)
                    continue;
                s[num].a = sq[i];
                s[num++].b = j;
            }
        }
        if (!num)
        {
            cout << "NONE\n";
            continue;
        }
        sort(s, s + num, cmp);
        for (int i = 0; i < num; i++)
        cout << s[i].a << " " << s[i].b << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lzyws739307453/article/details/83584625