这题略有点繁琐啊- - 先构造出所有的双平方数字在a数组里,p[i]表示i这个数字,在a数组的下标
穷举公差……但是公差其实是有范围的(小优化一下)
直接在双平方数字基础上穷举,用公差计算出的新的数字,在O(1)时间内判断出,是否还是双平方数…… 然后倒着算一下就行了。 程序自我感觉还算短……我没啥剪枝的说,下次想想。
这个很慢了……别人都0.4秒
Executing... Test 1: TEST OK [0.003 secs, 5932 KB] Test 2: TEST OK [0.005 secs, 5932 KB] Test 3: TEST OK [0.003 secs, 5932 KB] Test 4: TEST OK [0.005 secs, 5932 KB] Test 5: TEST OK [0.038 secs, 5932 KB] Test 6: TEST OK [0.138 secs, 5932 KB] Test 7: TEST OK [1.245 secs, 5932 KB] Test 8: TEST OK [2.595 secs, 5932 KB] Test 9: TEST OK [2.314 secs, 5932 KB]
/*
TASK:ariprog
LANG:C++
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
int N, M;
bool v[125001]={0};
int p[125001]; //这个数字,在a中的数组下标
int a[125001], t;//保存双平方数 从小到大排序
int count[125001]={0},ct(0);
typedef std::pair<int,int> PII;
PII Q[125001];
bool cmp(PII A , PII B)
{
if (A.second != B.second) return A.second < B.second;
return A.first < B.first;
}
int main()
{
freopen("ariprog.in", "r", stdin);
freopen("ariprog.out", "w", stdout);
scanf("%d%d", &N, &M);
for (int i = 0; i <= M; ++ i)
for (int j = 0; j <= M; ++ j) v[i * i + j * j] = true;
for (int i = 0; i <= M * M * 2; ++ i)
if (v[i])
{
a[++ t] = i;
p[i] = t;
}
for (int i = 1; i <= M * M * 2/ (N - 1); ++ i) //穷举公差
{
memset(count, 0, sizeof(count));//所有元素为结束点,公差为i的个数
for (int j = t; j >= 0; -- j) //穷举起点位置的元素下标
{
if (count[j]) continue; //如果j号元素已经穷举过了,那么直接跳过即可
int now(a[j]);
#define will (now - i)
for (count[j] = 1; v[will] && will >= 0; now = will)
{
count[p[will]] = count[p[now]] + 1;
if (count[p[will]] >= N) Q[++ct] = std::make_pair<int, int>(will, i);
}
}
}
std::sort(Q + 1, Q + 1 + ct, cmp);
for (int i = 1; i <= ct; ++ i) printf("%d %d\n",Q[i].first, Q[i].second);
if (!ct) printf("NONE\n");
return 0;
}