Ducci Sequence

题目描述:对于一个n元组(a1,a2,......an),可以对于每个数求出它和下一个数的差的绝对值,得到一个新的n元组(|a1-a2|,|a2-a3|,......|an-a1|)。重复这个过程,得到的序列称为Ducci序列,例如:(8,11,2,7)->(3,9,5,1)->(6,4,4,2)->(2,0,2,4)->(2,2,2,2)->(0,0,0,0)。也有的序列最终会循环。输入n元组(3<=n<=15),你的任务是判断它最终变成0还是循环。输入保证最多1000步就会变成0或者循环。

这一题比较搞笑,我最开始想复杂了,首先我把一个n元组转换成唯一的一个string,比如(8,11,2,7)转换成"8+11+2+7",然后对于每次转换的n元组用set存储起来,然后判断每一次计算产生的新的n元组产生的字符串是否已经产生过,若产生过则为“LOOP”。很遗憾的是,这种做法超时了。

然后我就一直思考怎么能够最快的,判断计算产生的新的n元组以前是否产生过,可惜的是多次尝试都是超时。后来重新审题发现一个关键,就是Ducci序列最终一定会是循环,或者是“0”序列。并且测试用例都是在1000次中就可以得到结果,所以可以采取最直接的方法,在1000次的循环中,判断新的n元组是否为“0”n元组,否则就是循环。实际在本题中,循环200次就足够了。。。我这里用了vector,我想直接用数组应该会更快一点。

代码如下(vs2012运行通过):

// 1594.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>

using namespace std;

vector<int> trans(vector<int> a)
{
    vector<int> b;
    for(int i=0;i<a.size();i++)
    {
        b.push_back(abs(a[i]-a[(i+1)%a.size()]));
    }
    return b;
}

bool isZero(vector<int> a)
{
    for(int i=0;i<a.size();i++)
    {
        if(a[i]!=0)
            return false;
    }
    return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int T;
    cin>>T;
    for(int i=0;i<T;i++)
    {
        vector<int> data;
        int n;
        cin>>n;
        for(int j=0;j<n;j++)
        {
            int num;
            cin>>num;
            data.push_back(num);
        }
		bool flag = false;
        for(int m=0;m<1000;m++)
        {
            if(isZero(data))
            {
				flag = true;
                cout<<"ZERO"<<endl;
                break;
            }
          
            data = trans(data);
        }
		if(flag==false)
		{
			cout<<"LOOP"<<endl;
		}
    }
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章