题目大意
循环数是这样的整数:它包含的数字都是独特不相同的,(如1111就是不正确的),而且没有0,例如81362。它有一个有趣的性质:
1.从左端开始,当前的数是多少就往右数几位(首尾相接,即认为最右边的数字之后是左边第一个数),对于81362,你将会停在一个新数字6上
2.重复上述过程,这回数6个数字因为刚刚停在6上。你将会停在2上
3.继续,(数2个数字),停在1
4.继续,(数1个数字),停在3
5.停在8,这个时候你已经接触了每个数字一次且仅一次。如果不是这样,那就不是循环数。
给定一个数M,找到并输出刚好比M大的下个循环数。使用unsigned long存储M
(copy form nocow)
题解
一个n位的数字,循环n次,如果n次都是到达了新的下标,没有重复,则找到答案。否则继续找下一个数字。
代码
#include <iostream>
#include <fstream>
#include <cstring>
#define MAXN 30
#define MOV(i, j) ((i)=((i)+(j))%k)
#define cin fin
#define cout fout
using namespace std;
ifstream fin("runround.in");
ofstream fout("runround.out");
typedef long long ll;
ll m;
int a[MAXN];
bool f[MAXN];
ll reverse(ll n) {
ll t = 0;
memset(f, false, sizeof(f));
while (n) {
t *= 10;
int tmp = n%10;
if (tmp == 0 || f[tmp]) return 0; //有0则这个数字直接跳过
t += n%10;
f[tmp] = true;
n/=10;
}
return t;
}
bool isRunround(ll n) {
int k = 0;
n = reverse(n); //反转一下,是为了方便使用下标,顺便检查有没有数字0
memset(a, 0, sizeof(a));
if (!n) return false; // 不能包含数字0
while (n) {
a[k++] = n%10;
n/=10;
}
int cnt = 0;
int p = 0;
memset(f, false, sizeof(f));
for (int i = 0; i < k; i++) {
MOV(p, a[p]);
if (f[p]) return false;
f[p] = true;
}
return true;
}
int main() {
cin >> m;
while (!isRunround(++m));
cout << m << endl;
return 0;
}