快速切题 usaco ariprog
题目:给定3<=n<=25,m<250,求m及以内的两两平方和能否构成为n的等差数列
1 WA 没有注意到应该按照公差-首项的顺序排序
2 MLE 尝试使用桶,但是实际上那可能是分散的,也即首项不一样
3 TLE 统计过多了,总之姿势不好
4 WA 当d=250*250*2时越界导致一直输出,实际上因为没打括号
应用时: 15min
实际用时:用了整整两天又1小时20分钟
思路: 先预处理出所有的平方和和平方和之差,对每个平方和都看看能否形成等差即可
思路误区: 因为 有重复统计的部分,因此陷入了“要把这部分除掉”的思路沼泽,而且还用桶装
/* ID: 53543391 PROG: ariprog LANG: C++ */ #include <cstring> #include <cstdio> using namespace std; const int maxsum=250*250*2+1; const int maxhlen=250*250; bool vis[maxsum]; int len[maxsum]; int use[maxhlen]; int heap[maxhlen]; int e[maxhlen]; int findd(int s,int d,int l){ for(int k=heap[s]+d;l>0&&k<maxsum;k+=d,l--){ if(!vis[k])return false; } return true; } int main(){ #define ONHOST #ifndef ONHOST freopen("ariprog.in","r",stdin); freopen("ariprog.out","w",stdout); #endif // ONHOST int l,m; scanf("%d%d",&l,&m); for(int i=0;i<=m;i++){ for(int j=0;j<=i;j++){ vis[i*i+j*j]=true; } } int mm=m*m*2; int hlen=0; int dhlen=0; bool fl=false; for(int i=0;i<=mm;i++){ if(vis[i]){ heap[hlen++]=i; } } int limit=l>1?mm/(l-1):mm; for(int i=0;i<hlen;i++){ for(int j=i+1;j<hlen;j++){ int d=heap[j]-heap[i]; if(d>limit)break; if(len[d]==0)use[d]=i; len[d]++; } } for(int d=0;d<=limit;d++){ if(len[d]>l-2){ for(int i=use[d];i<hlen;i++){ if(heap[i]+l-2*d>mm)break; if(findd(i,d,l-1)){ printf("%d %d\n",heap[i],d); fl=true; } } } } if(!fl)printf("NONE\n"); return 0; }