题目链接:USACO-Arithmetic Progressions
首先计算出所有的双平方数,有2e4个,然后排序后开始枚举。如果在一个枚举样例中,d*(n-1)+a_0>max(a),那么说明不可能组成等差数列,则退出,由于n>=3,这里对于a_0较大的情况完成了大量的剪枝。
还有一个剪枝就是从后往前枚举。因为后面较前面而言比较稀疏。因此枚举较少数量的等差数列后就能根据前一个剪枝break。
/*
ID: xdujlx1
PROG: ariprog
LANG: C++
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+7;
int a[maxn];
bool exist[maxn];
vector<pair<int,int> > ans;
int n,m;
bool check(int st,int d)
{
for(int i=st;i<=st+d*(n-1);i+=d)
if(!exist[i]) return false;
return true;
}
void ioinit()
{
freopen("ariprog.in","r",stdin);
freopen("ariprog.out","w",stdout);
}
int main()
{
ioinit();
scanf("%d%d",&n,&m);
int k=0;
for(int i=0;i<=m;i++)
for(int j=0;j<=m;j++)
{
a[k]=j*j+i*i;
exist[a[k++]]=true;
}
sort(a,a+k);
k=unique(a,a+k)-a;
for(int i=0;i<k;i++)
{
for(int j=i+1;j<k;j++)
{
if((a[j]-a[i])*(n-1)+a[i]>a[k-1]) break;
if(check(a[i],a[j]-a[i])) ans.push_back(make_pair(a[j]-a[i],a[i]));
}
}
sort(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++)
{
printf("%d %d\n",ans[i].second,ans[i].first);
}
if(ans.size()==0) puts("NONE");
return 0;
}