Sicily 1028. Hanoi Tower Sequence

1028. Hanoi Tower SequenceConstraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

Hanoi Tower is a famous game invented by the French mathematician Edourard Lucas in 1883. We are given a tower of n disks, initially stacked in decreasing size on one of three pegs. The objective is to transfer the entire tower to one of the other pegs, moving only one disk at a time and never moving a larger one onto a smaller.

The best way to tackle this problem is well known: We first transfer the n-1 smallest to a different peg (by recursion), then move the largest, and finally transfer the n-1 smallest back onto the largest. For example, Fig 1 shows the steps of moving 3 disks from peg 1 to peg 3.

Now we can get a sequence which consists of the red numbers of Fig 1: 1, 2, 1, 3, 1, 2, 1. The ith element of the sequence means the label of the disk that is moved in the ith step. When n = 4, we get a longer sequence: 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1. Obviously, the larger n is, the longer this sequence will be.Given an integer p, your task is to find out the pth element of this sequence.

Input

The first line of the input file isT, the number of test cases.Each test case contains one integerp(1<=p<10^100).

Output

Output the pth element of the sequence in a single line. See the sample for the output format.Print a blank line between the test cases.

Sample Input414100100000000000000Sample OutputCase 1: 1 Case 2: 3 Case 3: 3 Case 4: 15Problem Source

ZSUACM Team Member

这份是自己做的,,用时0.02s:

#include <stdio.h>#include <string.h>//通过观察规律可知,位置k上的数就是k可以被而整除的次数+1int ac[110] = {0};//用来高精度除以低精度的bool is_ok;//判断是否可以进行下一次除以2int divi(int first_pos, int length) {for (int i = first_pos; i < length; i++) {//高精度除以低精度if (ac[i] > 0) {if (ac[i] % 2 == 1) {ac[i + 1] += 10;}ac[i] /= 2;}}if (ac[length] > 0) {//假如length位置上有了大于零的(ac[i + 1] += 10;)说明length-1这一位出现了单数,已经不能整除了is_ok = false;return 0;}if (ac[first_pos] == 0)//更新数字长度return first_pos + 1;elsereturn first_pos;}int main() {int t, i, length, counter, kongzhi = 0, first_pos, j;scanf("%d", &t);for (i = 1; i <= t; i++) {char a[105] = {'\0'};is_ok = true;memset(ac, 0, sizeof(ac));scanf("%s", a);length = strlen(a);if (kongzhi)//输出的格式printf("\n");kongzhi = 1;if ((a[length – 1] – '0') % 2 == 1) {//假如是单数直接判断printf("Case %d: 1\n", i, 1);continue;}counter = 0;if (length <= 20) {//假如小于unsigned long long的最大值18446744073709551615直接判断char judge[] = "18446744073709551615";if (strcmp(a, judge) <= 0 || length <= 19) {unsigned long long sum = 0;for (j = 0; j < length; j++) {sum = sum * 10 + a[j] – '0' ;}while (sum % 2 == 0) {counter++;sum /= 2;}printf("Case %d: %d\n", i, counter + 1);continue;}}for (j = 0; j < length; j++) {ac[j] = a[j] – '0';}first_pos = 0;while (1) {//进行高精度除以低精度first_pos = divi(first_pos, length);if (is_ok)counter++;elsebreak;}printf("Case %d: %d\n", i, counter + 1);}return 0;}后来用了10^9的基数的数组提高效率,这次是0s:

#include <stdio.h>#include <string.h>#include <math.h>#define MAX_LENGTH 105//这里用的是基数为10的9储存方式,提高效率int base_index = 9;//基数为10的9次方long long unit_base = (long long)pow(10, 9);//基数大小long long unit[MAX_LENGTH / 9 + 9];//基数为10^9的最大长度数组long long per_base[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};//构建unit数组用到的char char_a[MAX_LENGTH];bool is_ok;//判断是否要进行下一次除以2int ready(int length) {memset(unit, 0, sizeof(unit));int unit_length = length % 9 == 0 ? length / 9 : length / 9 + 1;//计算所需unit长度int i, j, k;for (i = unit_length – 1, j = length – 1; i >= 0; i–) {//注意一定要从末尾开始构建for (k = 0; j >= 0; j–, k++) {if (k == 9)//每9位数更新一个跳到前一个unit下标break;unit[i] += (char_a[j] – '0') * per_base[k];}}return unit_length;}int divi(int first_pos, int last_pos) {if (unit[last_pos] % 2 == 1) {//假如假如末尾是单数直接不能继续除以2is_ok = false;return 0;}for (int i = first_pos; i <= last_pos; i++) {//高精度除法if (unit[i] % 2 == 1) {unit[i + 1] += unit_base;}unit[i] /= 2;}if (unit[first_pos] == 0)//更新unit数组的首位return first_pos + 1;elsereturn first_pos;}int main() {int t, i, length, counter, kongzhi = 0, first_pos, j;scanf("%d", &t);for (i = 1; i <= t; i++) {if (kongzhi)//输出的格式printf("\n");kongzhi = 1;memset(char_a, '\0', sizeof(char_a));scanf("%s", char_a);length = strlen(char_a);is_ok = true;if ((char_a[length – 1] – '0') % 2 == 1) {//假如是单数直接判断printf("Case %d: 1\n", i, 1);continue;}counter = 0;if (length <= 20) {//假如小于unsigned long long的最大值18446744073709551615直接判断char judge[] = "18446744073709551615";if (strcmp(char_a, judge) <= 0 || length <= 19) {unsigned long long sum = 0;for (j = 0; j < length; j++) {sum = sum * 10 + char_a[j] – '0' ;}while (sum % 2 == 0) {counter++;sum /= 2;}printf("Case %d: %d\n", i, counter + 1);continue;}}int unit_length = ready(length);first_pos = 0;while (1) {first_pos = divi(first_pos, unit_length – 1);//不断高精度除以2if (is_ok) {counter++;} else {break;}}printf("Case %d: %d\n", i, counter + 1);}return 0;}

也不要说曾经失去,失去的不是永远失去,得到的不是永远拥有,

Sicily 1028. Hanoi Tower Sequence

相关文章:

你感兴趣的文章:

标签云: