Problem:
Arithmetic Progressions
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)
1 4 37 4 2 8 29 8 1 12 5 12 13 12 17 12 5 20 2 24
MY GAIN:
一开始的算法糟糕透了。
1.并不是生成好双平方数然后依次去检验。
而是从0到max对a和b用两层循环去不断生成等差数列,然后一一去check是否为双平方数。算是穷举吧T T
举个例子,当n=18,m=100,max=2*100*100,这种算法所需的时间近,18*20000*20000=7.2*10^9 >> 2000000(穷举法使用范围)。
2.也没有使用快排。
而直接用了STL的优先级队列。一个struct类型数组保存a和b数对。先对b依次入了队,出队后再对相同b的a入队。
现在使用的这个算法是在别人的博客里学来的,基本思想如下:
1.对[0,m]范围之内的p,q生成所有双平方数,保存在Bisquare数组中,并建立了一个2*m*m+1大小的数组isBisquare来保存每个数是否为双平方数(便于检验ab)。
这里应当注意的是,new出来的bool数组默认值是true,要一一手动赋值。
2.对Bisquare数组快速排序。这即是对a的排序。
另外应注意到,Bisquare数组中其实是可能有重复元素的。经过快排,它们也移动到一起,便于后来skip之。
3.因为先对b排序,再对a排序,所以外层循环是b,内层是a。
为了保证等差数列最大元素a+(n-1)*b<=max,必须有(n-1)*b<=max。是b的循环条件。
而等差数列第一个元素即为a,故a根本不需从0到max-1依次++,只需要a依次是Bisquare中的元素即可。
由于有相等元素,需要用一个last来进行比较,skip相等的元素值。last的初始化位置需要注意。
4.判断a和b是否满足条件,满足则输出。