题意:给定页数M,求比M大的最小Runaround数。Runaround数有以下特征:
- 每位上的数字都不会与其他位重复,也不会有0的出现
- 如果某位上的数字为A,则下一步的动作就是从这一位开始往后数A个数(数到最后跳回首位)。
- 如果从这个数的第一位开始进行上述操作,并且再次回到首位的时候刚好每位数字访问一遍
- 满足上述条件的数就称为Runaround数
解题思路:
- 读入M
- 从M开始往后遍历
- 遍历过程中用一个数组存储遍历到的数的每一位,然后按照Runaround数的条件进行模拟,直到找到第一个Runaround数
代码:
/*
ID: zc.rene1
LANG: C
PROG: runround
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int digits[2][9];
int bit_map[9];
int Check(unsigned long num)
{
int len = 0;
int temp_bit = 0;
int i, next_index;
memset(digits, 0, 2*9*sizeof(int));
memset(bit_map, 0, 9*sizeof(int));
//get the digits
while (num != 0)
{
temp_bit = num%10;
if ((temp_bit==0) || (bit_map[temp_bit-1]==1))
{
return 0;
}
num /= 10;
digits[0][len++] = temp_bit;
bit_map[temp_bit-1] = 1;
}
//reverse the order
for (i=0; i<len/2; i++)
{
temp_bit = digits[0][i];
digits[0][i] = digits[0][len-i-1];
digits[0][len-i-1] = temp_bit;
}
//test if runround
next_index = (0 + digits[0][0])%len;
for (i=0; i<len; i++)
{
digits[1][next_index] = 1;
next_index = (next_index+digits[0][next_index])%len;
}
for (i=0; i<len; i++)
{
if (digits[1][i] != 1)
{
return 0;
}
}
return 1;
}
int main(void)
{
FILE *fin, *fout;
unsigned long M;
fin = fopen("runround.in", "r");
fout = fopen("runround.out", "w");
fscanf(fin, "%lu", &M);
while (1)
{
M++;
if (Check(M))
{
fprintf(fout, "%lu\n", M);
break;
}
}
return 0;
}