[USACO 1.4.3] Arithmetic Progressions

[題目描述]

Arithmetic Progressions

等差數列

一個等差數列是一個能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)
在這個問題中a是一個非負的整數,b是正整數。
寫一個程序來找出在雙平方數集合S中長度爲n的等差數列。
雙平方數集合是所有能表示成p2+q2的數的集合。

PROGRAM NAME: ariprog

INPUT FORMAT

第一行: N(3<= N<=25),要找的等差數列的長度。
第二行: M(1<= M<=250),搜索雙平方數的上界0 <= p,q <= M。

SAMPLE INPUT (file ariprog.in) 
5
7

OUTPUT FORMAT
如果沒有找到數列,輸出`NONE'。
如果找到了,輸出一行或多行, 每行由於二個整數組成:a,b
這些行應該先按b排序再按a排序。
將不會有隻多於10,000個等差數列。

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

[解題思路]

比較簡單的想法就是先M^2的找出S集合,然後枚舉首項元素q[i],再另外枚舉q[j],用q[j]-q[i]作爲公差b,然後判斷是否可行,最後排序輸出。

但實際效果並不理想,5s的時限,在第8個點TLE了...

再加剪枝,記錄S集合中的最大數爲up,枚舉公差之後可以O(1)的判斷是否有可行解,a+b*(n-1) > up 則直接break掉,效率可以直線上升,0.8s-AC...

話說回來,搜索的剪枝是很重要的,我還得多加練習,分析清楚整個搜索程序的複雜度,加上適當的剪枝。


[Code]

{
ID: zane2951
PROG: ariprog
LANG: PASCAL
}

program ariprog;
var
   v:array[0..125111] of boolean;
   q:array[0..125111] of longint;
   x,y:array[0..10001] of longint;
   ce,i,j,n,m,top,tp,up:longint;

//-----------qs------------
procedure qs(s,t:longint);
var
   i,j,ce,tmp:longint;

begin
   i:=s; j:=t; ce:=q[(i+j)>>1];
   repeat
      while q[i]<ce do inc(i);
      while q[j]>ce do dec(j);
      if i<=j then
         begin
            tmp:=q[i]; q[i]:=q[j]; q[j]:=tmp;
            inc(i); dec(j);
         end;
   until i>j;
   if i<t then qs(i,t); if s<j then qs(s,j);
end;

//----------qqss-----------
procedure qqss(s,t:longint);
var
   i,j,cex,cey,tmp:longint;

begin
   i:=s; j:=t; cey:=y[(i+j)>>1]; cex:=x[(i+j)>>1];
   repeat
      while (y[i]<cey) or (y[i]=cey) and (x[i]<cex) do inc(i);
      while (y[j]>cey) or (y[j]=cey) and (x[j]>cex) do dec(j);
      if i<=j then
         begin
            tmp:=x[i]; x[i]:=x[j]; x[j]:=tmp;
            tmp:=y[i]; y[i]:=y[j]; y[j]:=tmp;
            inc(i); dec(j);
         end;
   until i>j;
   if i<t then qqss(i,t); if s<j then qqss(s,j);
end;

//---------check-----------
function check(a,d:longint):boolean;
var
   i:longint;

begin
   for i:=2 to n-1 do
      if not v[a+d*i] then exit(false);
   exit(true);
end;

//----------main-----------
begin
   assign(input,'ariprog.in'); reset(input);
   assign(output,'ariprog.out'); rewrite(output);
   readln(n);
   readln(m);
   top:=0; up:=-1;
   for i:=0 to m do
      for j:=i to m do
         begin
            ce:=i*i+j*j;
            if not v[ce] then
               begin
                  if ce>up then up:=ce;
                  v[ce]:=true;
                  inc(top);
                  q[top]:=ce;
               end;
         end;
   qs(1,top);
   tp:=0;
   for i:=1 to top do
      for j:=i+1 to top do
         begin
            ce:=q[j]-q[i];
            if q[i]+ce*(n-1)>up then break;
            if check(q[i],ce) then
               begin
                  inc(tp);
                  x[tp]:=q[i];
                  y[tp]:=ce;
               end;
         end;
   if tp=0 then writeln('NONE')
      else
         begin
            qqss(1,tp);
            for i:=1 to tp do writeln(x[i],'':1,y[i]);
         end;
   close(input); close(output);
end.
發佈了41 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章