POJ 2952 循环数

总时间限制:
1000ms
内存限制:
65536kB
描述

若一个n位的数字串满足下述条件,则称其是循环数(cyclic):将这个数字串视为整数(可能带有前导0),并用任意一个 1 到 n 之间(包含1和n)的整数去乘它时, 会得到一个将原数字串首尾相接后,再在某处断开而得到的新数字串所对应的整数。例如,数字 142857 是循环数,因为:
142857 *1 = 142857
142857 *2 = 285714
142857 *3 = 428571
142857 *4 = 571428
142857 *5 = 714285
142857 *6 = 857142。

请写一个程序判断给定的数是否是循环数。

注意:在此题中,输入数字串允许带前导0,且前导0不能被忽略,例如“01”是两位数字串,而“1”是一位数字串。但将数字串转化为整数做乘法运算或比较运算时,可以忽略前导0。

输入
一行,一个长度在 2 到 60 位之间的数字串。
输出
一个整数,若输入的数字串是循环数,输出1,否则输出0。
样例输入
142857
样例输出
1


来源
1047

思路

直接思路就是大整数乘法,再判断字符频次相不相等。

#include<iostream>
#include<cstring>
using namespace std;
struct BigInt {
	int bsize;
	int digit[10000];
	void init() {
		bsize = 0;
		for (int i = 0; i < 10000; ++i)digit[i] = 0;
	}
	void set(char str[]) {
		init();
		int L = strlen(str);
		for (int i = L - 1, c = 1, t = 0, j = 0; i >= 0; --i) {
			int x = str[i] - '0';
			t += x * c;
			c *= c;
			++j;
			if (j == 1 || i == 0) {
				digit[bsize++] = t;
				t = 0;
				c = 1; 
				j = 0;
			}
		}
	}
	BigInt operator * (const int x)const {
		BigInt ret;
		ret.init();
		int carry = 0;
		for (int i = 0; i < bsize; ++i) {
			int tmp = digit[i] * x + carry;
			ret.digit[ret.bsize++] = tmp % 10;
			carry = tmp / 10;
		}
		if (carry != 0) {
			ret.digit[ret.bsize++] = carry;
		}
		return ret;
	}
};



int main()
{
	char str[65];
	int source[10];
	int ans[10];
	while (~scanf("%s", str)) {
		BigInt num;
		num.set(str);
		int L = strlen(str);
		for (int j = 0; j < 10; ++j)source[j] = 0;
		for (int i = 0; i < L; ++i) {
			source[str[i]-'0'] ++;
		}

			bool flag = true;
		for (int i = 1; i <= L; ++i) {
			for (int j = 0; j < 10; ++j)ans[j] = 0;
			BigInt tmp = num * i;
			for (int j = 0; j < tmp.bsize; ++j) {
				ans[tmp.digit[j]]++;
			}
			for (int j = 0; j < 10; ++j) {
				if (source[j] != ans[j]) {
					flag = false;
					break;
				}
			}
			if (!flag) {
				break;
			}
		}
		if (flag)printf("1\n");
		else
		{
			printf("0\n");
		}

	}
	return 0;
}

看到网上有大佬说循环数的一个特点是乘位数+1等于9,代码如下

#include <stdio.h>
#include <string.h>

#define BASE 10
#define N 60
char s[N + 1];

int main()
{
    int len, i;

    while(~scanf("%s", s)) {
        len = strlen(s);

        int ans = 0, flag = 1;
        for(i = len - 1; i; i--) {
            ans += (s[i] - '0') * (len + 1);
            if(ans % BASE != 9) {flag = 0; break;}
            ans /= BASE;
        }
        if(flag) {
            len = (len + 1) / 2;
            for(i = 0; i < len; i++) {
                if(s[i] + s[i + len] - 2 * '0' != 9) {
                    flag = 0;
                    break;
                }
            }
        }

        printf("%d\n", flag);
    }

    return 0;
}

后半段不是很理解了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值