要求输出下一个 runaround number (定义见原题)
思路很简单,就是 枚举 并 判断,因为判断是否为 runaround number 是常数时间,然后可能枚举的范围也并不特别大,所以可行。
但是,还是可以做一点点小小优化的
记这个数的长度为 len, 根据 runaround number 的定义,我们注意到
1)len 这个 digit 不可能出现在 runaround number 中。因为一旦碰到它,下一次还是它。
2)runaround number 各个位上数字的总和 sum % len == 0。 这样才能满足每个数字遇到一次,又回到最初的数字。
顺带再提一下 数字 与 字符串 的转化,用了 istringstream 和 ostringstream
AC代码如下:
/*
PROB: runround
LANG: C++
ID: fan_0111
*/
#include <iostream>
#include <cstdio>
#include <sstream>
#include <string>
#include <cstring>
using namespace std;
typedef long long LL;
int toInt(string& s) {
istringstream in(s);
int x;
in >> x;
return x;
}
string toString(int x) {
ostringstream out;
out << x;
return out.str();
}
bool check(LL x) {
string s = toString(x);
int len = s.length();
bool exist[10] = {0};
for (int i = 0; i < len; ++i) {
if (s[i] == len || s[i] == '0') return false;
if (exist[s[i]-'0']) return false;
exist[s[i]-'0'] = true;
}
memset(exist, 0, sizeof(exist));
int sum = 0;
for (int i = 0; i < len; ++i) sum += s[i] - '0';
if (sum % len) return false;
int p = 0, tot = 1;
exist[s[0]-'0'] = true;
while (true) {
if (tot == len) return true;
p = (p+s[p]-'0') % len;
if (exist[s[p]-'0']) return false;
++tot;
exist[s[p]-'0'] = true;
}
}
int main() {
freopen("runround.in", "r", stdin);
freopen("runround.out", "w", stdout);
string s;
cin >> s;
int num = toInt(s);
for (LL i = num+1;; ++i) {
if (check(i)) {
cout << i << endl;
break;
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
后来看了 ANALYSIS,有一种解法是递归地生成 各数位digit不同的 数,然后判断是否满足 runaround number 的其他定义,也可以。