usaco2.2 runround

来源:互联网 发布:送人钢笔推荐 知乎 编辑:程序博客网 时间:2024/06/05 05:14

题目链接


要求输出下一个 runaround number (定义见原题)


思路很简单,就是 枚举 并 判断,因为判断是否为 runaround number 是常数时间,然后可能枚举的范围也并不特别大,所以可行。


但是,还是可以做一点点小小优化的

记这个数的长度为 len, 根据 runaround number 的定义,我们注意到

1)len 这个 digit 不可能出现在 runaround number 中。因为一旦碰到它,下一次还是它。

2)runaround number 各个位上数字的总和 sum % len == 0。 这样才能满足每个数字遇到一次,又回到最初的数字。


顺带再提一下 数字 与 字符串 的转化,用了 istringstream 和 ostringstream


AC代码如下:


/*PROB: runroundLANG: 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 的其他定义,也可以。

0 0
原创粉丝点击