题目描述
循环数是一种没有重复数字且不含 0 并具有一些有趣性质的整数。
我们以 81362 为例:
如果从最左边的那个数字(在这里是8)开始,向右数该数字位(当数到最右边的数字时,若还没有数完,则从左边第一位继续数),你将在一个新的数字处停下(如果没停在新数字上,则这个数不是循环数)。对于本例,从 8 开始右数 8 位:1 3 6 2 8 1 3 6,将停在 6 上。
在新停下的位置,继续重复上一个操作,也就是从 6 开始右数 6 位:2 8 1 3 6 2,将停在 2 上。
再次重复此操作,从 2 开始右数 2 位:8 1,将停在 1 上。
继续重复此操作,从 1 开始右数 1 位:3,将停在 3 上。
最后,从 3 开始右数 3 位:6 2 8,将停在 8 上。
循环数满足在所有的数字上均停留一次后,又能够回到出发点上。如果在所有的数字上均停留一次后,没有回到出发点,则这个数不是循环数。
给定一个数字 M,请你找到第一个比 M 大的循环数是多少。
样例
输入样例:
81361
输出样例:
81362
C++ 代码
#include<bits/stdc++.h>
using namespace std;
int n;
int num[10];
int book[10];//用来标记这个数字循环了几次
int main() {
cin >> n;
for(int i = n + 1; ; i++)//从输入的数的后一个开始查找
{
memset(book, 0, sizeof book);//开始将标记设为零
int len = log10(i) + 1;//计算该数的位数
int t = i;
int flat = 0, glat = 0, hlat=0;
for(int j = 1; j <= len; j ++)//将这个数分解并存入num数组中
{
num[j] = t / pow(10, len - j);
if(num[j] == 0)//如果这个数中有零直接结束再寻找下一个
{
flat = 1;
break;
}
t = t % int(pow(10, len - j));
}
for(int p = 1; p < len; p ++)//检查这个数组中是否有相等的数
for(int q = p + 1; q <= len; q ++)
if(num[p] == num[q]) //如果有直接结束再寻找下一个
{
flat = 1;
break;
}
if(flat == 0)//如果不含零或相等的元素,就进行下一步判断
{
int k = 1;
book[k] = 1;//从头开始判断并标记
while(1)
{
//找他的下一个数并标记
if(num[k]%len + k <= len)
k = num[k] % len + k;
else
k = (num[k] % len + k) % len;
book[k] += 1;
for(int o = 1; o <= len; o ++)
if(book[o] == 2)//如果有一个数循环了两次就结束
{
hlat=1;
break;
}
if(hlat == 1)
break;
}
for(int l = 1; l < len; l ++)//如果循环两次的不是第一个数或者有的数没有循环到就不符合条件
if(book[1] != 2 || book[l + 1] != 1) glat = 1;
if(glat == 0)//符合条件就输出
for(int m = 1; m <= len; m ++)
printf("%d",num[m]);
}
if(flat == 0 && glat == 0)//不符合条件就找下一个数
break;
}
}