第一篇CSDN博客,USACO - Arithmetic Progressions

 
Arithmetic Progressions

An arithmetic progression is a sequence of the form a, a+b, a+2b, ..., a+nb where n=0,1,2,3,... . For this problem, a is a non-negative integer and b is a positive integer.

Write a program that finds all arithmetic progressions of length n in the set S of bisquares. The set of bisquares is defined as the set of all integers of the form p2 + q2 (where p and q are non-negative integers).

TIME LIMIT: 5 secs

PROGRAM NAME: ariprog

INPUT FORMAT

Line 1:N (3 <= N <= 25), the length of progressions for which to search
Line 2:M (1 <= M <= 250), an upper bound to limit the search to the bisquares with 0 <= p,q <= M.

SAMPLE INPUT (file ariprog.in)

5
7

OUTPUT FORMAT

If no sequence is found, a singe line reading `NONE'. Otherwise, output one or more lines, each with two integers: the first element in a found sequence and the difference between consecutive elements in the same sequence. The lines should be ordered with smallest-difference sequences first and smallest starting number within those sequences first.

There will be no more than 10,000 sequences.

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


题目是明显的暴搜,5s的时间,我看时间还是挺多的,就尝试着自己按最暴力最原始的方式来完成这题,思路是这样的:根据n m大概确定a b的范围,对a b循环搜索,对每一个a b,检验是否是双平方数,然后用vector存起来,最后排序输出。结果可想而知,超时。

 
TASK: ariprog
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 3184 KB]
   Test 2: TEST OK [0.000 secs, 3184 KB]
   Test 3: TEST OK [0.000 secs, 3052 KB]
   Test 4: TEST OK [0.022 secs, 3184 KB]
   Test 5: TEST OK [3.650 secs, 3184 KB]
  > Run 6: Execution error: Your program (`ariprog') used more than
        the allotted runtime of 5 seconds (it ended or was stopped at
        5.378 seconds) when presented with test case 6. It used 3180 KB of
        memory. 

        ------ Data for Run 6 ------
        18 
        100 
        ----------------------------
    Test 6: RUNTIME 5.378>5 (3180 KB)

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

struct arip
{
    int a, b;
    arip(int a1, int b1):a(a1),b(b1){}
};

int n, m, i, j, a, b, m2, temp;
bool found = 0;
int square[250+1] = {0,	1,	4,	9,	16,	25,	36,	49,	64,	81,	100,	121,	144,	169,	196,	225,	256,	289,	324,	361,	400,	441,	484,	529,	576,
                    625,	676,	729,	784,	841,	900,	961,	1024,	1089,	1156,	1225,	1296,	1369,	1444,	1521,	1600,	1681,	1764,	1849,	1936,	2025,	2116,	2209,	2304,	2401,
                    2500,	2601,	2704,	2809,	2916,	3025,	3136,	3249,	3364,	3481,	3600,	3721,	3844,	3969,	4096,	4225,	4356,	4489,	4624,	4761,	4900,	5041,	5184,	5329,	5476,
                    5625,	5776,	5929,	6084,	6241,	6400,	6561,	6724,	6889,	7056,	7225,	7396,	7569,	7744,	7921,	8100,	8281,	8464,	8649,	8836,	9025,	9216,	9409,	9604,	9801,
                    10000,	10201,	10404,	10609,	10816,	11025,	11236,	11449,	11664,	11881,	12100,	12321,	12544,	12769,	12996,	13225,	13456,	13689,	13924,	14161,	14400,	14641,	14884,	15129,	15376,
                    15625,	15876,	16129,	16384,	16641,	16900,	17161,	17424,	17689,	17956,	18225,	18496,	18769,	19044,	19321,	19600,	19881,	20164,	20449,	20736,	21025,	21316,	21609,	21904,	22201,
                    22500,	22801,	23104,	23409,	23716,	24025,	24336,	24649,	24964,	25281,	25600,	25921,	26244,	26569,	26896,	27225,	27556,	27889,	28224,	28561,	28900,	29241,	29584,	29929,	30276,
                    30625,	30976,	31329,	31684,	32041,	32400,	32761,	33124,	33489,	33856,	34225,	34596,	34969,	35344,	35721,	36100,	36481,	36864,	37249,	37636,	38025,	38416,	38809,	39204,	39601,
                    40000,	40401,	40804,	41209,	41616,	42025,	42436,	42849,	43264,	43681,	44100,	44521,	44944,	45369,	45796,	46225,	46656,	47089,	47524,	47961,	48400,	48841,	49284,	49729,	50176,
                    50625,	51076,	51529,	51984,	52441,	52900,	53361,	53824,	54289,	54756,	55225,	55696,	56169,	56644,	57121,	57600,	58081,	58564,	59049,	59536,	60025,	60516,	61009,	61504,	62001,
                    62500};

bool check_bisquare() {
    for(i = 0; i <= n-1; i++) {
        found = 0;
        for(j = 0; temp = a+i*b, square[j] <= temp; j++)
            if((square[j] <= m2) && (temp - square[j] <= m2) && binary_search(square, square+251 ,temp - square[j])) {
                found = 1;
                break;
            }
        if(found == 0)
            return false;
    }
    return true;
}

bool cmp(const arip& a1, const arip& a2) {
    return a1.b < a2.b ? 1 : (a1.b == a2.b ? a1.a < a2.a : 0);
}

int main()
{
    freopen("ariprog.in", "r", stdin);
    freopen("ariprog.out", "w", stdout);

    vector<arip> vec;
    scanf("%d%d", &n, &m);
    m2 = m*m;
    for(b = 1; b <= (m2<<2)/(n-1); b++)
        for(a = 0; a <= (m2<<2)-(n-1)*b; a++)
            if(check_bisquare())
                vec.push_back(arip(a, b));
    if(vec.size() == 0) {
        printf("NONE\n");
    }else {
        sort(vec.begin(), vec.end(), cmp);
        for(vector<arip>::iterator idx = vec.begin(); idx != vec.end(); idx++)
        printf("%d %d\n", idx->a, idx->b);
    }
    return 0;
}


上网看了一下别人的思路,原来是应该强搜双平方数,而不是强搜a b,双平方数最多有250*250*2 = 125000,可以接受,在双平方数中先强搜确定a,再根据a+nb<2*m*m确定b的强搜范围,对每个a b判断所有的序列是否属于双平方数。ACM虽然接触了一下,但仅仅限于选修课上。个人感觉每道题都不太会,看到题目只会强搜,深一点的算法题就不会了。但听了一位师兄说,只要坚持搞ACM一个月,一定会有感觉的。正在努力当中。。。

 

经过一天的努力,参考了别人的代码,终于通过了,运行最慢才0.302s<<5s,庆祝一下!!

/*
LANG: C++
TASK: ariprog
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

struct arip
{
    int a, b;
    arip(int a1, int b1):a(a1),b(b1){}
};

int n, m, i, j, a, b, k, cnt = 0, temp = 0, m2;
bool square_bit[125000+10] = {false};
int square_num[125000+10]  = {0};
vector<arip> vec;

void db() {
    for(int i = 0; i < cnt; i++)
        cout<<square_num[i]<<endl;
}

void make() {
    for(i = 0; i <= m; i++)
        for(j = 0; j <= m; j++) {
            temp = i*i+j*j;
            if(square_bit[temp] == 0) {
                square_bit[temp] = true;
                square_num[cnt++] = temp;
            }
        }
    sort(square_num, square_num+cnt);
    m2 = m*m;
}

bool check_bisquare(int a, int b) {
    for(k = 0; k <= n-1; k++)
        if(square_bit[a+k*b] == 0)
             return false;
    return true;
}

void cal_ab() {
    for(i = 0,a = 0; i < cnt; i++, a = square_num[i])
        for(j = i+1, b = square_num[j]-square_num[i]; a+(n-1)*b <= 2*m2 && j < cnt; j++, b = square_num[j]-square_num[i]) {
            //cout<<a<<" ,"<<b<<endl;
            if(check_bisquare(a, b))
                vec.push_back(arip(a, b));
        }
}

bool cmp(const arip& a1, const arip& a2) {
    return a1.b < a2.b ? 1 : (a1.b == a2.b ? a1.a < a2.a : 0);
}

int main()
{
    freopen("ariprog.in", "r", stdin);
    freopen("ariprog.out", "w", stdout);

    scanf("%d%d", &n, &m);
    make();
    //db();

    cal_ab();

    if(vec.size() == 0) {
        printf("NONE\n");
    }else {
        sort(vec.begin(), vec.end(), cmp);
        for(vector<arip>::iterator idx = vec.begin(); idx != vec.end(); idx++)
        printf("%d %d\n", idx->a, idx->b);
    }
    return 0;
}

前后相差这么远,可以看到不是强搜就是简单的,从什么角度搜用什么来保存状态怎样剪枝,这些都影响到程序的效率。

这次学会了空间换时间,下标作为变量保存状态。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值