原文地址: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
#include
#define rep(i,j,k) for(i=j;i
using namespace std;
const int N = 105;
vector<int> piles[N];
int temp[N], temp_cnt = 0;
int pile[N], height[N];
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;
}