您的位置:首页 > 其它

UVa 100|The 3n+1 Problem|暴力|坑点多

2017-09-25 23:30 435 查看
原文地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=36

题目翻译

计算机科学的问题经常被划分到已有的确切问题类别上(比如NP,无解,递归等)。本题需要你分析一个未知类别的算法的性质。
考虑这样的一个算法:


1 input n
2 print n
3 if n = 1 then STOP
4   if n is odd then n = 3n + 1
5   else n = n / 2
6 GOTO 2


输入22,算法中的n将会按照以下顺序变化:

22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1


有人认为对于任意输入的正整数,上述算法能在有限步数内结束。尽管算法很简单,但是仍然不知道这个推测是不是正确的。我们已经审查了0~1,000,000内的所有整数满足该推测。

给定n,我们可以知道上面的那个序列的数字个数k(比如n=22,数字的个数是16)。对于任意的两个数i和j,你的任务是找出i和j之间(包括i和j)的某个数,其算法序列数字个数最多,输出这个序列的数字个数。

输入

输入有n组测试数据。每个测试数据一行两个整数i和j(0<i,j<10,000)。

你可以假定中间运算结果不会超过32位整数范围。

输出

对于每个测试数据,输出一行3个整数i,j和k。i和j即为输入对应的i和j。

样例输入

1 10
100 200
201 210
900 1000


样例输出

1 10 20
100 200 125
201 210 89
900 1000 174


题解

暴力即可,中间运算显然可以缓存,不过本题数据而言不需要啦。

#include <cstdio>
#include <vector>
#define rep(i,j,k) for(i=j;i<k;++i)
using namespace std;
const int N = 105;
vector<int> piles
;
int temp
, temp_cnt = 0;
int pile
, height
;

template<class T>
void internal(int from, int h, T callback) {
while (piles[from].size() >= h) {
int x = *piles[from].rbegin();
piles[from].pop_back();
int pile_id = callback(x);
piles[pile_id].push_back(x);
height[x] = piles[pile_id].size();
pile[x] = pile_id;
}
}

void restoreBlocks(int from, int h) {
internal(from, h, [](int x){ return x; });
}

void moveBlocks(int from, int h, int to) {
internal(from, h, [=](int x){ return to; });
}

int main() {
int n, from, to, i, t = 0;
char op[8], prep[8];

rep(i,0,n) pile[i] = i, height[i] = 1;

while (scanf("%s%d%s%d", op, &from, prep, &to) == 4
&& op[0] != 'q') {

if (prep[0] == 'o') // onto
restoreBlocks(pile[to], height[to]);

if (op[0] == 'm') // move
restoreBlocks(pile[from], height[from]);

moveBlocks(pile[from], height[from], pile[to]);

}
rep(i,0,n) {
printf("%d:", i);
for (auto element : piles[i])
printf(" %d", element);
printf("\n");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: