FZU1080 奇怪的数列
Posted dlvguo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FZU1080 奇怪的数列相关的知识,希望对你有一定的参考价值。
Problem Description 题目链接
有一个长度为n (1<n<=100) 的数列,其中一些元素是正整数,其余元素是0。这些正整数会同时加倍,并将加倍后的数二等分后向左右两侧的元素转移,从而从一个状态转入其后继状态,如下图的一个状态:
0 6 0 8 0
经一次加倍转移后,其后继状态为:
6 0 14 0 8
特别要注意的是:第一个元素的数加倍后,向左边移动的数又回到原处。最后一个元素的数加倍后,向右边移动的数消失。如上述状态再经一次加倍转移后的后继状态是:
6 20 0 22 0
有些状态不可能是另一些状态的后继状态,我们称这样状态为“根状态”。给出一个状态,求它的根状态。Input
第一行仅包含一个表示测试例个数的正整数n。以下 2n 行为测试例的输入数据。
每个测试例输入两行,第一行是一个正整数,为数列的长度。第二行为给定的一个数列,两数之间用一个空格隔开。
每个测试例输入两行,第一行是一个正整数,为数列的长度。第二行为给定的一个数列,两数之间用一个空格隔开。
Output
每个测试例输出一行,包含数列的根状态下的各个元素,两数之间用一个空格隔开。
Sample Input
2
5
5 10 1 9 0
8
1 0 1 1 0 3 9 1
Sample Output
0 0 1 0 0
1 0 1 1 0 3 9 1
#include <iostream> #include <stdio.h> using namespace std; /* 思路:找规律将矩阵回退,当下一个矩阵中含有负数的时候,说明当前矩阵为根矩阵:如n为奇数的时候 1层: 0 6 0 8 0 2层: 6 0 14 0 8 3层: 6 20 0 22 0 因为最右边向右移会消除于是有:[2][4]=[3][5] 之后从右向左递推 [2][2]=[3][5]-[2][4]... 之后从左向右递推 [2][3]=[3][2]-[3][1]... */ int main() { int num[2][105] = {0}; int n, t; scanf("%d", &n); while (n--) { int now = 0, pre = 1; bool tag = false; scanf("%d", &t); for (int i = 1; i <= t; i++) { scanf("%d", &num[now][i]); } //计算上一个数组含有负数的时候 说明当前数组为根 while (!tag) { num[pre][t - 1] = num[now][t]; for (int i = t - 3; i >= 1; i -= 2) { num[pre][i] = num[now][i + 1] - num[pre][i + 2]; if (num[pre][i] < 0) { tag = true; break; } } if (tag) break; // 注意n为奇的时候 [x][1]要另外算 循环上述循环不会遍历到 if (t % 2) { num[pre][1] = num[now][1] - num[pre][2]; if (num[pre][1] < 0) { break; } } for (int i = 3; i <= t; i += 2) { num[pre][i] = num[now][i - 1] - num[pre][i - 2]; if (num[pre][i] < 0) { tag = true; break; } } if (tag) break; now = pre; pre = (pre + 1) % 2; } printf("%d", num[now][1]); for (int i = 2; i <= t; i++) { printf(" %d", num[now][i]); } cout << endl; } }
以上是关于FZU1080 奇怪的数列的主要内容,如果未能解决你的问题,请参考以下文章