USACO 1.4.3 Arithmetic Progressions

题意:

      给定等差数列的长度N, 求出满足此长度的等差数列, 其中所有数字来源于集合平方数(即x = a^2 + b^2 a, b都是非负整数)

       给定a, b的范围为 0 <= a, b <= M

     要求答案按照起始数字的大小排序, 如果起始数字大小相同,按照等差数列公差排序

 

解法:

      搜索。

      首先预处理求出所有的“平方数”,存入一个数组,因为范围不大,可以直接开辟一个数组记录这个数是否出现过

      一开始看到按照顺序输出,打算按照答案的方法枚举,即从小到大枚举公差,然后枚举等差数列起点

      但是到第五组数据就搜爆了。按照公差大小可以取值范围为[1, M * M + M * M),其中M最大可以取到200多,太大

      重新设计,将平方数数组进行排序,然后按照[起点和第二个点]进行枚举(即同时确定两个点),

  加入一个剪枝。 如果数列最后一个预计的数已经不在平方数数组当中,就不再继续当前搜索

     

/*
ID: lsswxr1
PROG: ariprog
LANG: C++
*/
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
using namespace std;

#define USACO
#ifdef USACO
#define cin fin
#define cout fout
#endif
//////////////////////////////////////////////////////////////////////////
///宏定义
const int  INF = 1000000000;
const int MAXN = 251;
const int maxn = MAXN;
///全局变量 和 函数


int dsquareNum[maxn * maxn * 2];
bool isCal[maxn * maxn * 2 + 10];
//bool isCal[maxn  + 10];
int cnt;
void calUpds(int up)
{
    for (int i = 0; i <= up; i++)
    {
        for (int j = i; j <= up; j++)
        {
            int cur = i * i + j * j;
            if (!isCal[cur])
            {
                isCal[cur] = true;
                dsquareNum[cnt++] = cur;
            }
        }
    }
}

int N, M;
struct node
{
    int startnum;
    int dif;
    bool operator < (const node& T) const
    {
        if (dif != T.dif)
        {
            return dif < T.dif;
        }
        else
        {
            return startnum < T.startnum;
        }
    }
};
node ans[10010];
int main()
{


#ifdef USACO    
    ofstream fout ("ariprog.out");
    ifstream fin ("ariprog.in");
#endif   
    while (cin >> N >> M)
    {
        bool outputs = false;
        cnt = 0;
    
        int cntAns = 0;
        memset(isCal, false, sizeof(isCal));
        //        memset(isCal, false, sizeof(isCal));
        calUpds(M);
        sort(dsquareNum, dsquareNum + cnt);
        
        //枚举起点
        for (int i = 0; i < cnt; i++)
        {
            //枚举第二个点
            for (int j = i + 1; j < cnt; j++)
            {
                bool flag = true;
                int d = dsquareNum[j] - dsquareNum[i];
                int cur = dsquareNum[i] + d * (N - 1);  //注意是N - 1

                //剪枝
                if (cur > dsquareNum[cnt - 1])
                {
                    break;
                }

                //检查是否满足条件
                for (int k = 2; k < N; k++)
                {
                    if (!isCal[dsquareNum[i] + d * k])
                    {
                        flag = false;
                        break;
                    }
                }
                if (flag)
                {
                    ans[cntAns].startnum = dsquareNum[i];
                    ans[cntAns].dif = d;
                    cntAns++;
                }
            }
        }

        if (cntAns != 0)
        {
            sort(ans, ans + cntAns);

            for (int i = 0; i < cntAns; i++)
            {
                cout << ans[i].startnum << " " << ans[i].dif << endl;
            }
        }
        else
        {
            cout << "NONE" << endl;
        }

    }


    ///结束
    return 0;
}

 

     

posted on 2013-12-24 22:29  小书包_Ray  阅读(253)  评论(0编辑  收藏  举报

导航