[USACO1.4]等差数列 Arithmetic Progressions

预处理出来所有的双平方数,然后枚举地一个和第二个数。
中间要加一个剪枝。因为知道了首项和公差和项数就能求出最后一项是不是可行的了。

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vector>
#include <bitset>
#include <cmath>
#include <queue>
#include <ctime>
#include <set>
#include <map>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define go(i,k) for(int i=head[k],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
using namespace std;
typedef long long ll;
typedef double db;
const int inf=0x3f3f3f3f;
inline int rd() {
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
    return x*f;
}
const int N=256;
int sqr[N*N<<1];
bool vis[N*N<<2];
int n,m,cnt;
struct Node{int a,b;}q[10005];
bool cmp(Node x,Node y) {return x.b==y.b?x.a<y.a:x.b<y.b;}
bool cmp2(int x,int y) {return x>y;}
int main() {
#ifdef HSZ
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
#endif
    n=rd(),m=rd();
    int ans=0;
    fo(i,0,m) 
        fo(j,0,m) 
            if(!vis[i*i+j*j]) vis[i*i+j*j]=1,sqr[++cnt]=i*i+j*j;
    sort(sqr+1,sqr+1+cnt);
    fo(i,1,cnt)fo(j,i+1,cnt){
        int d=sqr[j]-sqr[i],p=sqr[i],cnt=0;bool flag=0;
        if(p+d*(n-1)>m*m*2) break;
        while(vis[p]) {
            cnt++;
            p+=d;
            if(cnt==n) {q[++ans]=(Node){sqr[i],d};flag=1;break;}
        }
    }
    sort(q+1,q+1+ans,cmp);
    if(!ans) {puts("NONE");return 0;}    fo(i,1,ans) printf("%d %d\n",q[i].a,q[i].b);
    return 0;
}
posted @ 2018-10-25 11:23  SWHsz  阅读(307)  评论(0编辑  收藏  举报