題目描述:對於一個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;
}