arithmeticprogressions - codetrick
There will be no more than 10,000 sequences.
看了题解发现漏考虑了一个很重要的优化,枚举首项的时候应该直接枚举双平方数,这就要求将双平方数另存一个a[],当然是有序的。其次对于公差,也应该是直接枚举a[]中两个数的差更好。另外两个优化,一个最有效的是我想到的,另一个细节是判断一个数列时从后往前判断。
http://jackneus.com/programming-archives/arithmetic-progressions/
首先决定在算术级数中找双平方还是在双平方中找算术级数。直觉是在双平方数中找算术级数,首先生成所有的双平方数,保存在一个boolean数组中,这个数组大小为250×250×2=125000。然后外层循环取a(从1开始在双平方数中取),内层循环取b(从1开始取到(125000-a)/(N-1),因为满足a+(N-1)*b <=125000),得到a,b后要验证是否能构成长度为n的算术级数,若能则储存结果。最后按b,a升序的顺数输出a,b。
http://jusaco.blogspot.com/2013/07/arithmetic-progressions-solution.html
public static void main(String[] args) throws Exception {
BufferedReader in = new BufferedReader(new FileReader("ariprog.in"));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(
"ariprog.out")),true);
int N = Integer.parseInt(in.readLine());
int M = Integer.parseInt(in.readLine());
// max: 250 * 250 * 2 = 125000
int MM2 = M*M*2;
boolean[] bisquares = new boolean[MM2+1];
for(int p = 0; p <= M; p++)
for(int q = p; q<= M; q++)
bisquares[p*p + q*q] = true;
List<int[]> res = new ArrayList<int[]>();
for(int a = 0; a < MM2; a++){
if(!bisquares[a]) continue;
label:
for(int b = 1; b <= (MM2-a)/ (N-1); b++){
for(int i = 1; i<= N-1; i++){
if(!bisquares[a + b * i])
continue label;
}
res.add(new int[]{a,b});
}
}
Collections.sort(res,new Comparator<int[]>(){
public int compare(int[] o1, int[] o2) {
if(o1[1] < o2[1]) return -1;
if(o1[1] > o2[1]) return 1;
if(o1[0] < o2[0]) return -1;
if(o1[0] < o2[0]) return 1;
return 0;
}});
if(res.size() == 0) out.println("NONE");
for(int[] ab : res)
out.println(ab[0]+ " " + ab[1]);
System.exit(0);
}
}
https://github.com/TomConerly/Competition-Programming/blob/master/USACO/Chapter1/ariprog.java
Read full article from arithmeticprogressions - codetrick
An arithmetic progression is a sequence of the form a, a+b, a+2b, ..., a+nb where n=0,1,2,3,... . For this problem, a is a non-negative integer and b is a positive integer.
Write a program that finds all arithmetic progressions of length n in the set S of bisquares. The set of bisquares is defined as the set of all integers of the form p2 + q2 (where p and q are non-negative integers). TIME LIMIT: 5 secs
PROGRAM NAME: ariprog
INPUT FORMAT
| Line 1: | N (3 <= N <= 25), the length of progressions for which to search |
| Line 2: | M (1 <= M <= 250), an upper bound to limit the search to the bisquares with 0 <= p,q <= M. |
SAMPLE INPUT (file ariprog.in)
5 7
OUTPUT FORMAT
If no sequence is found, a singe line reading `NONE'. Otherwise, output one or more lines, each with two integers: the first element in a found sequence and the difference between consecutive elements in the same sequence. The lines should be ordered with smallest-difference sequences first and smallest starting number within those sequences first.There will be no more than 10,000 sequences.
SAMPLE OUTPUT (file ariprog.out)
http://mangogao.com/read/83.html1 4 37 4 2 8 29 8 1 12 5 12 13 12 17 12 5 20 2 24
首先直接把所有能表示成p2+q2的数算出来,存入一个表中。然后每次从表里选出两个数,以它们的差作为公差,然后扩展,看能否扩展到指定的位。最后将答案进行排序即可。首先用bool组表示所有范围内的双平方数,枚举每个数列的起点和公差,搜索层数的话用循环分别加0~N-1个公差进行判断。考虑到数据比较大,当首项加上N-1个公差超过了最大范围时break可以稍微优化一点。
int len, q, total = 0;bool ok, is_pfs[MAX_NUM] = {0};struct Prog{ int a, b;} ans[MAX_ANS_NUM];bool compare(Prog x, Prog y){ if (x.b < y.b || (x.b == y.b && x.a < y.a)) return true; return false;}void get_pfs(){ for (int i = 0; i <= q; ++i) for (int j = i; j <= q; ++j) is_pfs[i * i + j * j] = true; // for (int i = 0; i < 2*q*q; ++i) // { // if (is_pfs[i]) cout <<"[Debug] pfs: "<<i<<endl; // }}void solve(){ int i, j=0; for (i = 0; i <= 2 * q * q; ++i) { //find the b for (j = 1; j <= 2 * q * q; ++j) { //stop properly if ((i + j * (len - 1)) > 2 * q * q) break; // suppose it's good ok = true; // check this prog for (int k = 0; k < len; ++k) if (!is_pfs[i + j * k]) { ok = false; break; } if (ok) { ans[total++].a = i; ans[total - 1].b = j; // cout <<"[Debug] a = "<<i<<" b = " << j <<" "<< total<<endl; } } }}int main(){ ifstream fin("ariprog.in"); fin >> len >> q; fin.close(); //get all the pfs get_pfs(); //find the first number of a prog solve(); //sort the answer sort(ans, ans + total, compare); ofstream fout("ariprog.out"); if (total == 0) fout << "NONE" << endl; else for (int i = 0; i < total; ++i) fout << ans[i].a << " " << ans[i].b << endl; fout.close(); return 0;}看了题解发现漏考虑了一个很重要的优化,枚举首项的时候应该直接枚举双平方数,这就要求将双平方数另存一个a[],当然是有序的。其次对于公差,也应该是直接枚举a[]中两个数的差更好。另外两个优化,一个最有效的是我想到的,另一个细节是判断一个数列时从后往前判断。
http://jackneus.com/programming-archives/arithmetic-progressions/
struct prog{
int base;
int increm;
bool operator < (const prog & b) const{
return increm < b.increm;
}
};
int N;
vector<prog> progs;
bool valid(vector<bool>& S, int base, int step){
for(int i = 1; i < N; i++){
if(!S[base + step * i]) return false;
}
return true;
}
int main(){
ifstream in("ariprog.in");
ofstream out("ariprog.out");
int M;
in >> N >> M;
vector<bool> S(M * M * 2);
for(int i = 0; i < S.size(); i++) S[i] = false;
for(int p = 0; p <= M; p++){
for(int q = 0; q <= M; q++){
S[p * p + q * q] = true;
}
}
for(int i = 0; i < S.size(); i++){
if(S[i]){
for(int j = 1; j < (S.size() - i) / N + 2 * N; j++){
if(valid(S, i, j)){
prog solut;
solut.base = i;
solut.increm = j;
progs.push_back(solut);
}
}
}
}
if(progs.size() != 0){
sort(progs.begin(), progs.begin() + progs.size());
for(int i = 0; i < progs.size(); i++){
out << progs[i].base << " " << progs[i].increm << endl;
}
}
else out << "NONE" << endl;
}
http://leonlu.iteye.com/blog/1125404首先决定在算术级数中找双平方还是在双平方中找算术级数。直觉是在双平方数中找算术级数,首先生成所有的双平方数,保存在一个boolean数组中,这个数组大小为250×250×2=125000。然后外层循环取a(从1开始在双平方数中取),内层循环取b(从1开始取到(125000-a)/(N-1),因为满足a+(N-1)*b <=125000),得到a,b后要验证是否能构成长度为n的算术级数,若能则储存结果。最后按b,a升序的顺数输出a,b。
| public static void main(String[] args) throws Exception{ BufferedReader in = new BufferedReader(new FileReader("ariprog.in")); | |
| PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter( | |
| "ariprog.out")),true); | |
| // read data | |
| int N = Integer.parseInt(in.readLine()); | |
| int M = Integer.parseInt(in.readLine()); | |
| // max: 250 * 250 * 2 = 125000 | |
| int MM2 = M*M*2; | |
| // generate bisquares into a boolean array | |
| // loop times: 251 * 252 /2 = 31626 | |
| boolean[] bisquares = new boolean[MM2+1]; | |
| for(int p = 0; p <= M; p++) | |
| for(int q = p; q<= M; q++) | |
| bisquares[p*p + q*q] = true; | |
| // search and pruning | |
| List<int[]> res = new ArrayList<int[]>(); | |
| for(int a = 0; a < MM2; a++){ | |
| if(!bisquares[a]) continue; | |
| label: | |
| for(int b = 1; b <= (MM2-a)/ (N-1); b++){ // a+ (N-1) * b <= MM2 | |
| for(int i = 1; i<= N-1; i++){ | |
| if(!bisquares[a + b * i]) | |
| continue label; | |
| } | |
| res.add(new int[]{a,b}); | |
| } | |
| } | |
| // sort and print | |
| Collections.sort(res,new Comparator<int[]>(){ | |
| public int compare(int[] o1, int[] o2) { | |
| if(o1[1] < o2[1]) return -1; | |
| if(o1[1] > o2[1]) return 1; | |
| if(o1[0] < o2[0]) return -1; | |
| if(o1[0] < o2[0]) return 1; | |
| return 0; | |
| }}); | |
| if(res.size() == 0) out.println("NONE"); | |
| for(int[] ab : res) | |
| out.println(ab[0]+ " " + ab[1]); | |
| System.exit(0); | |
| } |
public static void main(String[] args) throws Exception {
BufferedReader in = new BufferedReader(new FileReader("ariprog.in"));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(
"ariprog.out")),true);
int N = Integer.parseInt(in.readLine());
int M = Integer.parseInt(in.readLine());
// max: 250 * 250 * 2 = 125000
int MM2 = M*M*2;
boolean[] bisquares = new boolean[MM2+1];
for(int p = 0; p <= M; p++)
for(int q = p; q<= M; q++)
bisquares[p*p + q*q] = true;
List<int[]> res = new ArrayList<int[]>();
for(int a = 0; a < MM2; a++){
if(!bisquares[a]) continue;
label:
for(int b = 1; b <= (MM2-a)/ (N-1); b++){
for(int i = 1; i<= N-1; i++){
if(!bisquares[a + b * i])
continue label;
}
res.add(new int[]{a,b});
}
}
Collections.sort(res,new Comparator<int[]>(){
public int compare(int[] o1, int[] o2) {
if(o1[1] < o2[1]) return -1;
if(o1[1] > o2[1]) return 1;
if(o1[0] < o2[0]) return -1;
if(o1[0] < o2[0]) return 1;
return 0;
}});
if(res.size() == 0) out.println("NONE");
for(int[] ab : res)
out.println(ab[0]+ " " + ab[1]);
System.exit(0);
}
}
Read full article from arithmeticprogressions - codetrick