原文翻译:
翻译者:timgreen
转载自:OIBH
一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)
在这个问题中a是一个非负的整数,b是正整数。
写一个程序来找出在双平方数集合S中长度为n的等差数列。
双平方数集合是所有能表示成p2+q2的数的集合。
PROGRAM NAME: ariprog
INPUT FORMAT
第一行: N(3<= N<=25),要找的等差数列的长度。
第二行: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M。
SAMPLE INPUT (file ariprog.in)
5
7
OUTPUT FORMAT
如果没有找到数列,输出`NONE'。
如果找到了,输出一行或多行, 每行由于二个整数组成:a,b
这些行应该先按b排序再按a排序。
将不会有只多于10,000个等差数列。
SAMPLE OUTPUT (file ariprog.out)
1 4
37 4
2 8
29 8
1 12
5 12
13 12
17 12
5 20
2 24
这题的思路应该说还是比较容易想的,不过要已开始就想到不TLE的就有点难了,可以把形 如p^2+q^2的数都存起来,后来就可以直接去数组里面取了。
接下来就是找适合的a和b了。
我一开始的代码是最原始的,就是一个一个找,
for(int i = 0;i < index1-n+1;i++)
{
a = num[i];
for(int j = i+1;j < index1;j++)
{
b = num[j]-a;
now = a+b;
count = 2;
if(a + b*(n-1) > max_num)//这里是表示不可能找到满足条件的a和b
continue;
for(int k = j+1;k < index1;k++)
{
if(now+b == num[k])
{
now = num[k];
count++;
if(n == count)//如果找到,就退出
{
node[index2].a = a;
node[index2++].b = b;
break;
}
}
if(num[k] > now + b)//表示不可能找到合适的a和b
break;
}
}
可是这样TLE,死在第7组数据上,听说第8组更强悍的数据。
后来搜了份报告,发现挺不错的,
代码如下
for(int i = 0;i < index1-n+1;i++)
{
a = num[i];
for(int j = i+1;j < index1;j++)
{
b = num[j]-a;
now = a+b;
count = 2;
if(a + b*(n-1) > max_num)
continue;
can = true;
for(int k = 2;k < n;k++)
{
if(!isexict[a+b*k])//isexict[i]表示i可以表示成p^2+q^2不
{
can = false;
break;
}
}
if(can)
{
node[index2].a = a;
node[index2++].b = b;
}
}
}
我的思路是一直找,找合适的,但是上面这个就是找不合适的,这样肯定会快,因为这里面不合适的多得多。这就是枚举时不同的方法,差别很大啊
不过还有人能在第8组数据上之用0.63S,可是我的用了1.46S,看来还有更好的,继续学习。
不过现在我再改了下,第8组数据也只要0.43S了,也就是把下第二个程序的
if(a + b*(n-1) > max_num)
continue;
中的continue;改成break;因为当这个不可能的时候,下面的b只会比这个还大,那肯定不行,所以就直接break了