原文翻译:
翻译者:timgreen
转载自:OIBH
一个等差数列是一个能表示成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
Hash+搜索的时候要注意剪枝
USER: A e [chenh193]
TASK: ariprog
LANG: C++
Compiling...
Compile: OK
Executing...
Test 1: TEST OK [0.000 secs, 9716 KB]
Test 2: TEST OK [0.000 secs, 9720 KB]
Test 3: TEST OK [0.000 secs, 9720 KB]
Test 4: TEST OK [0.022 secs, 9716 KB]
Test 5: TEST OK [0.000 secs, 9720 KB]
Test 6: TEST OK [0.043 secs, 9716 KB]
Test 7: TEST OK [0.324 secs, 9716 KB]
Test 8: TEST OK [0.637 secs, 9720 KB]
Test 9: TEST OK [0.540 secs, 9716 KB]
All tests OK.
Your program ('ariprog') produced all correct answers! This is your submission #9 for this problem. Congratulations!
第8组数据几乎是极限数据了,没优化以前>5s.优化以后0.6x秒就过了...
- /*
- ID: chenh193
- PROG: ariprog
- LANG: C++
- */
- #include<iostream>
- #include<algorithm>
- using namespace std;
- //hash
- const int SIZE=524288;
- const int BUF=5000;
- //record
- struct rec
- {
- int a,b;
- bool operator<(const rec & o)const{return b<o.b||(b==o.b&&a<o.a);}
- }r[10001];
- struct Hash
- {
- int a,b,next;
- }hash[SIZE+BUF];
- bool dbit[251*251*2],flag[SIZE];
- int M,N,ULimit,Rlen=0,table[22000],Tlen=0,buf=SIZE;
- void inhash(int a,int b)
- {
- int key=((a+b)&(SIZE-1));
- if(!flag[key])
- {
- hash[key].a=a;
- hash[key].b=b;
- hash[key].next=-1;
- flag[key]=true;
- return;
- }
- while(key!=-1)
- {
- if(hash[key].a==a&&hash[key].b==b)
- return;
- if(hash[key].next==-1)
- break;
- key=hash[key].next;
- }
- hash[key].next=++buf;
- hash[buf].a=a;
- hash[buf].b=b;
- hash[buf].next=-1;
- return;
- }
- bool isinhash(int a,int b)
- {
- int key=((a+b)&(SIZE-1));
- if(!flag[key]) return false;
- while(key!=-1)
- {
- if(hash[key].a==a&&hash[key].b==b)
- return true;
- if(hash[key].next==-1)
- break;
- key=hash[key].next;
- }
- return false;
- }
- void dfs()
- {
- int i,j,k,LLimit=ULimit/(N-1),ta,tb,tmp,times;
- for(i=0;i<Tlen;i++)
- for(j=i+1;j<Tlen;j++)
- {
- if((tb=table[j]-table[i])>LLimit)break;
- ta=table[i];
- if((tmp=ta+(N-1)*tb)>ULimit||!dbit[tmp])continue;
- if(isinhash(ta,tb))continue;
- times=0;
- for(k=ta;k<=ULimit;k+=tb)
- {
- if(!dbit[k])
- break;
- times++;
- }
- if(times>=N)
- {
- times=times-N+1;
- tmp=ta;
- for(k=1;k<=times;k++)
- {
- r[Rlen].a=tmp;
- r[Rlen].b=tb;
- inhash(r[Rlen].a,r[Rlen].b);
- Rlen++;
- tmp+=tb;
- }
- }
- }
- }
- int main()
- {
- int p,q,i;
- scanf("%d%d",&N,&M);
- for(p=0;p<=M;p++)for(q=0;q<=M;q++)dbit[p*p+q*q]=true;
- ULimit=2*M*M;
- for(i=0;i<=ULimit;i++)if(dbit[i])table[Tlen++]=i;
- dfs();
- sort(r,r+Rlen);
- for(i=0;i<Rlen;i++)
- printf("%d %d/n",r[i].a,r[i].b);
- if(Rlen==0)
- puts("NONE");
- return 0;
- }