题目原文
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
分析
提交代码
/*
ID:
PROG: ariprog
LANG: C++
*/
#include <fstream>
#include <iostream>
#include <set>
#include <vector>
using namespace std;
int main()
{
ifstream fin("ariprog.in");
ofstream fout("ariprog.out");
int N,M;
fin >> N >> M;
vector<bool> bisqures(M*M*2+1,false);
for (int p=0;p<=M;p++)
{
for (int q=0;q<=M;q++)
{
bisqures[q*q + p*p] = true;
}
}
int b=1;
bool none = true;
while((N-1) * b <= 2*M*M)
{
int a = 0;
while(a + (N-1) * b <= 2 * M * M)
{
bool flag = true;
for (int i=0;i!=N;i++)
{
flag = flag && bisqures[a + i*b];
if(!flag)
break;
}
if(flag)
{
none = false;
fout << a << " " << b << endl;
}
a++;
}
b++;
}
if(none)
fout << "NONE" << endl;
return 0;
}
值得注意的是,原先我判断每个元素是否符合指定形式的时候是这样的
<span style="white-space:pre"> </span>bool flag = true;
for (int i=0;i!=N;i++)
{
flag = flag && bisqures[a + i*b];
}
if(flag)
{
none = false;
fout << a << " " << b << endl;
}
由于实际上只有有一个元素不符合,这一个等差数列就已经是不符合要求了,上述代码中做了多次多余的判断,第一次提交的时候运行超时了,改过之后就没有超时问题了。
提交结果
USER: TASK: ariprog LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.014 secs, 3500 KB] Test 2: TEST OK [0.008 secs, 3500 KB] Test 3: TEST OK [0.008 secs, 3500 KB] Test 4: TEST OK [0.008 secs, 3500 KB] Test 5: TEST OK [0.038 secs, 3500 KB] Test 6: TEST OK [0.159 secs, 3500 KB] Test 7: TEST OK [1.939 secs, 3500 KB] Test 8: TEST OK [4.333 secs, 3500 KB] Test 9: TEST OK [3.785 secs, 3500 KB] All tests OK.
官方参考答案
#include <stdio.h>
#include <assert.h>
#include <string>
using namespace std;
// open files
FILE *fin = fopen ("ariprog.in", "r");
FILE *fout = fopen ("ariprog.out", "w");
// global variables
unsigned int N, M, maxMM;
unsigned int numbers [65000];
unsigned int number_size = 0;
unsigned char num_available [125001];
unsigned char dist_available [125001];
int have_res = 0;
int skipstep = 1;
// read the input
int read_input () {
fscanf (fin, "%d %d", &N, &M);
return 0;
}
int cmp_int (const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
void asm_num (int a, int b) {
for (unsigned int n = 1; n < N; n++)
if (num_available [a + n * b] == 0) return;
fprintf (fout, "%d %d\n", a, b);
have_res ++;
if (have_res==1)
skipstep = b;
}
void asm_num () {
for (unsigned int b = 1; b < maxMM; b+=skipstep) {
if (dist_available [b]) {
for (unsigned int p = 0; p < number_size && numbers [p] + (N -
1) * b <= maxMM; p++)
asm_num (numbers [p], b);
}
}
}
int process () {
memset (num_available, 0, sizeof (unsigned char) * 125001);
memset (dist_available, 0, sizeof (unsigned char) * 125001);
for (unsigned int m1 = 0; m1 <= M; m1++) {
for (unsigned int m2 = m1; m2 <= M; m2++) {
int n = m1 * m1 + m2 * m2;
if (!num_available [n]) {
num_available [n] = 1;
numbers [number_size++] = n;
}
}
}
qsort (numbers, number_size, sizeof (unsigned int), cmp_int);
maxMM = M * M + M * M;
for (unsigned int n1 = 0; n1 < number_size; n1++) {
unsigned int _n1 = numbers [n1];
for (unsigned int n2 = n1 + 1; n2 < number_size && _n1 + (numbers
[n2] - _n1) * (N - 1) <= maxMM; n2++) {
assert (numbers [n2] - _n1 >= 0 && numbers [n2] - _n1 < 125001);
if (num_available [_n1 + (numbers [n2] - _n1) * (N - 1)] &&
num_available [_n1 + (numbers [n2] - _n1) * (N - 2)])
dist_available [numbers [n2] - _n1] = true;
}
}
asm_num ();
if (!have_res) fprintf (fout, "NONE\n");
return 0;
}
int main () {
read_input ();
process ();
fclose (fin);
fclose (fout);
return 0;
}
#include <fstream>
#include <iostream>
using namespace std;
void quicksort (int[], int ,int);
int pivotlist (int[], int,int);
ofstream out ("ariprog.out");
int n;
int main () {
ifstream in ("ariprog.in");
bool array[125001] = {false}, noneF;
int m, upper, upperdef, def, p;
int places[300000], pl = 0;
noneF = true;
in>>n>>m;
for (int i = 0; i <= m; i++)
for (int j = 0; j <= m; j++) {
if (!array[i*i+j*j]) {
places[pl] = i*i+j*j; //Saving generated numbers
pl++;
}
array[i*i+j*j] = true;
}
upper = 2*m*m;
upperdef = upper/(n-1);
quicksort (places, 0, pl-1);
for ( def = 1; def<=upperdef; def++) // Loop to check for solutions
// It looks for solutions in
// correct order so you
// print the solution directly
// without sorting first, thnx to who said:
// Trade Memory for Speed !!
{
for ( p = 0; places[p]<=(upper-((n-2)*def)); p++) {
bool is;
is = true;
int where;
for (int c = (n-1); c>=0 ; c--)
if (!array[places[p]+c*def]) {
is = false;
where = (p+c*def);
break;
}
if (is) {
noneF = false;
out<<places[p]<<" "<<def<<endl;
}
}
}
if (noneF)
out<<"NONE"<<endl;
return 0;
}
void quicksort (int array[], int start, int last) {
int pivot;
if (start < last) {
pivot = pivotlist(array, start,last);
quicksort (array, start,pivot-1);
quicksort (array, pivot+1,last);
}
}
int pivotlist(int array[], int f, int l) {
int pivotpoint;
int pivotvalue, temp;
pivotvalue = array[f];
pivotpoint = f;
for (int i = f+1;i<=l; i++) {
if (array[i]<pivotvalue) {
pivotpoint++;
temp = array[i];
array[i] = array[pivotpoint];
array[pivotpoint] = temp;
}
}
temp = array[f];
array[f] = array[pivotpoint];
array[pivotpoint] = temp;
return pivotpoint;
}