USACO-Section2.2 Runaround Numbers [其他][模拟]

18 篇文章 0 订阅
3 篇文章 0 订阅

题目大意

循环数是这样的整数:它包含的数字都是独特不相同的,(如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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值