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; }