Ducci Sequence 解题心得
原题贴上
A Ducci sequence is a sequence of n-tuples of integers. Given an n-tuple of integers (a1, a2, ... , an), the next n-tuple in the sequence is formed by taking the absolute differences of neighboring integers:
Ducci sequences either reach a tuple of zeros or fall into a periodic loop. For example, the 4-tuple sequence starting with 8,11,2,7 takes 5 steps to reach the zeros tuple:
The 5-tuple sequence starting with 4,2,0,2,0 enters a loop after 2 steps:
Given an n-tuple of integers, write a program to decide if the sequence is reaching to a zeros tuple or a periodic loop.
Input
Your program is to read the input from standard input. The input consists of T test cases. The number of test casesT is given in the first line of the input. Each test case starts with a line containing an integer n(3n15), which represents the size of a tuple in the Ducci sequences. In the following line, n integers are given which represents the n-tuple of integers. The range of integers are from 0 to 1,000. You may assume that the maximum number of steps of a Ducci sequence reaching zeros tuple or making a loop does not exceed 1,000.
Output
Your program is to write to standard output. Print exactly one line for each test case. Print `LOOP' if the Ducci sequence falls into a periodic loop, print `ZERO' if the Ducci sequence reaches to a zeros tuple.
The following shows sample input and output for four test cases.
Sample Input
4
4
8 11 2 7
5
4 2 0 2 0
7
0 0 0 0 0 0 0
6
1 2 3 1 2 3
Sample Output
ZERO LOOP ZERO LOOP
分析:
题目让我们求循环出现的时候和全0出现的时候, 其实,全0出现后紧接着就会出现循环,所以我们只需专注于找到循环出现。
这里的循环也就是数字的排列出现重复,也就是发现重复即找到。
想到去重,第一个想到的便是STL中的set可以直接保证每个键是唯一的,然而这里这并不能将重复出现的时候标记出来,达不到解题。接着就很自然的想到“标记法”,即——将每种情形和一个bool值对应,出现过记为true,没出现过记为false。每次新出现一个情形先判断对应的bool值,然后就可以判断重复没有啦。
一种情形与一个值对应,最近正在学STL,然后立马就想到了map。
map<A,B> 应题目要求,A为一个有序对比较适合,所以可以用一个结构体将多个数字组成一个整体,B就很自然的使用bool类型。
可是还有一个问题,map<A,B> 里面的A必须要是定义了<操作符的,因为map判断A的唯一性必须要通过<符号比较,具体的判别机制是(a<b,b<a 有且仅有一个成立 ->a b不相等 //否则a b相等),这就需要我们重载A里的<操作符。
按照判别机制,我如下重载
1 bool operator <(const gro &b) const {
2 for (int i = 0; i < n; i++){
3 if (g[i] != b.g[i]) return g[i]<b.g[i];
4 }
5 return false;
6 }
有了这个认识,然后就可以写代码了,如下:
1 #include<iostream>
2 #include<algorithm>
3 #include<map>
4 #include<stdio.h>
5 using namespace std;
6 const int N = 16;
7 bool isloop = 0;
8
9
10 struct gro
11 {
12 int g[N];
13 int n;
14 void read ()
15 {
16 for (int i = 0; i < n; i++)
17 {
18 cin >> g[i];
19 }
20 }
21 bool iszero(){
22 for (int i = 0; i < n; i++){
23 if (g[i] != 0){
24 return false;
25 }
26 }
27 return true;
28 }
29
30 bool operator <(const gro &b) const {
31 for (int i = 0; i < n; i++){
32 if (g[i] != b.g[i]) return g[i]<b.g[i];
33 }
34 return false;
35 }
36
37 void change()
38 {
39 int temp = g[0];
40 for (int i = 0; i < n - 1; i++)
41 {
42 g[i] = abs(g[i] - g[i + 1]);
43 }
44 g[n - 1] = abs(temp - g[n - 1]);
45 }
46
47 } g1;
48
49
50
51
52
53 map <gro, bool> group;
54
55 int main()
56 {
57 int T;
58 cin >> T;
59 while (T--){
60 cin >> g1.n;
61 g1.read();
62 group.clear(); // 因为有多组数据,记得要清空!!!
63 group[g1] = true;
64 for (int k = 0; k < 1000; k++){
65 g1.change();
66 if (group[g1] == true){
67 isloop = true;
68 break;
69 }
70 group[g1] = true; //一定要记得!!!
71 }
72 if (g1.iszero() == true){
73 puts("ZERO");
74 }
75 else {
76 puts("LOOP");
77 }
78 bool isloop = false;
79 }
80
81 return 0;
82 }
骚年,加油奋斗吧,毕竟水题。