【3004】循环数
Time Limit: 3 second
Memory Limit: 2 MB
【问题描述】
“循环数”指那些不包括数字0的没有重复数字的整数(比如81362),并且同时具有一个有趣的性质, 就像
这个例子: 如果你从最左边的数字开始 (在这个例子中是8) 数从左边这个数字到右边 (如果数到了最右边,回
到最左边), 你会停止在另一个新的数字 (如果没有停在一个不同的数字上,这个数就不是循环数)。就像:
8 1 3 6 2 从最左边接下去数8个数字: 1 3 6 2 8 1 3 6 所以下一个数字是6.
重复这样做 (这次从“6”开始数6个数字) 并且你会停止在一个新的数字上: 2 8 1 3 6 2,也就是2.
再这样做 (这次数两个): 8 1;
再一次 (这次一个): 3;
又一次: 6 2 8 这时你回到了起点。
所以81362是循环数。
在从每一个数字开始数1次之后.如果你在从每一个数字开始数一次以后没有回到起点,你的数字不是一个循环数。
给你一个数字 M (在1到9位之间), 找出第一个比 M大的循环数, 并且一定能用一个无符号长整形数装下。
【输入】
仅仅一行, M 的值
【输出】
仅仅一行,第一个比M大的循环数
【输入样例】
81361
【输出样例】
81362
【题解】
有更好的解法。但是我直接暴力模拟了。在代码里面说吧,太恶心了。有点复杂;
【代码】
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
string s1;
bool bo[1000];
int pret;
void input_data()
{
cin >> s1;
}
void get_ans()
{
bool flag = false; //flag函数用于判断循环的出口
int l = s1.size(); //获取数字的长度
int t = 0;
for (int i = 0;i <= l-1;i++) //先把输入的字符串转成整形数字
t = t*10 + s1[i] - '0';
pret = t; //pret是最初输入的数字
int rest = l;
while (!flag)
{
bool ok = true; //ok用于判断 有0 ,有重复数字的情况
for (int i = 0;i <= l-1;i++) //判断是否有0
if (s1[i] == '0')
{
ok = false;
break;
}
for (int i = 1;i <= 9;i++)
bo[i] = false;
for (int i = 0;i <= l-1;i++) //用于判断是否有重复的数字
if (!bo[s1[i]-'0'])
bo[s1[i]-'0'] = true;
else
{
ok = false;
break;
}
if (ok) //如果以上情况都未出现就试试这个数是否为循环数 也还好 才40行左右
{
int j = 0; //j表示现在到数字各个数字的指针
int k = s1[0] - '0'; //k表示接下来要走几步
for (int i = 0;i <= l-1;i++) //用于判断是否到了之前已经走过的地方
bo[i] = true;
bo[j] = false; //初始位置已经走过了
rest --;//rest用于记录剩余的数字
flag = true;
for (int mm = 1;mm <= l;mm++) //表示要检验的次数 ,检验l-1次时所有数字都被走过,当走第l次时,检验能否回到原点。
{
for (int i = 1;i <= k;i++) //先跳k步
{
j++;
if (j > (l-1)) j = 0;
}
if (!bo[j] && rest!=0) //如果遇到了之前跳到的数字,就判断一下是否已经没有剩余数字
{
flag = false;
break;
}
if (!bo[j] && j!=0) //又或者回到了第一次扫描的位置
{
flag = false;
break;
}
bo[j] = false; //如果这个数字之前没出现过 现在就标记下
rest--; //剩余的数字递减
k = s1[j] - '0'; //获取下一个需要循环的次数
}
if (t == pret) flag = false; //因为是大于输入的数字 所以不能和输入数字相同
if (flag == true) //如果以上约束都过了 就可以了 输出就好
{
printf("%d\n",t);
return;
}
}
t++; //尝试下一个数字 直接递增
string ts;
int ll = 0;
int tt = t;
while (tt > 0) //tt用于把数字转化成string类 存在ts字符串中。
{
ts[++ll] = (tt % 10) + '0';
tt = tt / 10;
}
for (int i = ll;i >= 1;i--)//这样存是倒序的,所以再把它正序下。
s1[ll-i] = ts[i];
rest = ll; //更新剩下的数字
l = ll;//更新数字的长度
}
}
int main()
{
input_data();
get_ans();
return 0;
}
【代码2更优秀的解法,pascal版】
这个程序直接用数组记录某个数是否可以由其他数字i通过走a[i]步走到。如果所有的位置都能通过其他位置通过走x步到,那就是一个循环数。要注意死循环的情况排除掉,比如12
1->2 ,但是2 会一直到2,不能到1.这种情况要排除。
var n:longint;
a,b:array[1..100] of integer;
function yes:boolean;
var s:string;l,i:integer;
begin str(n,s);
if pos('0',s)>0 then exit(false);
l:=length(s);
for i:=1 to l do val(s[i],a[i]);
fillchar(b,sizeof(b),0);
for i:=1 to l do
begin inc(b[a[i]]);
if b[a[i]]>1 then exit(false); end;
fillchar(b,sizeof(b),0);
for i:=1 to l do
begin if (i+a[i]-1)mod l+1=i then exit(false);
inc(b[(i+a[i]-1)mod l+1]); end;
for i:=1 to l do if b[i]=0 then exit(false);
yes:=true; end;
begin
readln(n);
inc(n);
while not yes and (n<maxlongint) do inc(n);
writeln(n);
end.

浙公网安备 33010602011771号