快速切题 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;
}


posted @ 2014-08-10 10:53  雪溯  阅读(210)  评论(0编辑  收藏  举报