POJ 1016 Numbers That Count 模拟题目

Description

"Kronecker's Knumbers" is a little company that manufactures plastic digits for use in signs (theater marquees, gas station price displays, and so on). The owner and sole employee, Klyde Kronecker, keeps track of how many digits of each type he has used by maintaining an inventory book. For instance, if he has just made a sign containing the telephone number "5553141", he'll write down the number "5553141" in one column of his book, and in the next column he'll list how many of each digit he used: two 1s, one 3, one 4, and three 5s. (Digits that don't get used don't appear in the inventory.) He writes the inventory in condensed form, like this: "21131435". 

The other day, Klyde filled an order for the number 31123314 and was amazed to discover that the inventory of this number is the same as the number---it has three 1s, one 2, three 3s, and one 4! He calls this an example of a "self-inventorying number", and now he wants to find out which numbers are self-inventorying, or lead to a self-inventorying number through iterated application of the inventorying operation described below. You have been hired to help him in his investigations. 

Given any non-negative integer n, its inventory is another integer consisting of a concatenation of integers c1 d1 c2 d2 ... ck dk , where each ci and di is an unsigned integer, every ci is positive, the di satisfy 0<=d1<d2<...<dk<=9, and, for each digit d that appears anywhere in n, d equals di for some i and d occurs exactly ci times in the decimal representation of n. For instance, to compute the inventory of 5553141 we set c1 = 2, d1 = 1, c2 = 1, d2 = 3, etc., giving 21131435. The number 1000000000000 has inventory 12011 ("twelve 0s, one 1"). 

An integer n is called self-inventorying if n equals its inventory. It is called self-inventorying after j steps (j>=1) if j is the smallest number such that the value of the j-th iterative application of the inventory function is self-inventorying. For instance, 21221314 is self-inventorying after 2 steps, since the inventory of 21221314 is 31321314, the inventory of 31321314 is 31123314, and 31123314 is self-inventorying. 

Finally, n enters an inventory loop of length k (k>=2) if k is the smallest number such that for some integer j (j>=0), the value of the j-th iterative application of the inventory function is the same as the value of the (j + k)-th iterative application. For instance, 314213241519 enters an inventory loop of length 2, since the inventory of 314213241519 is 412223241519 and the inventory of 412223241519 is 314213241519, the original number (we have j = 0 in this case). 

Write a program that will read a sequence of non-negative integers and, for each input value, state whether it is self-inventorying, self-inventorying after j steps, enters an inventory loop of length k, or has none of these properties after 15 iterative applications of the inventory function.

Input

A sequence of non-negative integers, each having at most 80 digits, followed by the terminating value -1. There are no extra leading zeros.

Output

For each non-negative input value n, output the appropriate choice from among the following messages (where n is the input value, j is a positive integer, and k is a positive integer greater than 1): 
n is self-inventorying 
n is self-inventorying after j steps 
n enters an inventory loop of length k 
n can not be classified after 15 iterations

Sample Input

22 
31123314 
314213241519 
21221314 
111222234459 
-1

Sample Output

22 is self-inventorying 
31123314 is self-inventorying 
314213241519 enters an inventory loop of length 2 
21221314 is self-inventorying after 2 steps 
111222234459 enters an inventory loop of length 2 

Source


本题没有多少技巧,就是考编程能力。

其中的注意的地方有:

1 数数字-基本算法,很多题目都会用上,本题利用Hash表计算每个数字出现的次数就可以,其中有个坑:注意大于9的数,多位数字转换成字符串

2 map的运用,当然可以使用STL,如果直接手动实现,或者使用Trie算法实现,那么本题难度就大大增加了。

3 简单的计算问题和读清楚题意,比如本题要求是大于15步,就需要额外处理的,不小心就掉坑里了。


下面程序标明的易出错还是挺容易让人掉坑里的。快到坑里来-_-|||

#include <stdio.h>
#include <vector>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <limits.h>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;

string countNum(string &s)
{
	int hashNum[10] = {0};
	int n = (int)s.size();
	for (int i = 0; i < n; i++)
	{
		if (s[i] < '0' || s[i] > '9') break;
		hashNum[s[i]-'0']++;
	}
	string rs;
	for (int i = 0; i < 10; i++)
	{
		if (hashNum[i])
		{
			int j = hashNum[i];
			string t;//易错处:有多位的数字的时候
			while (j) t += char(j%10 + '0'), j /= 10;
			reverse(t.begin(), t.end());
			t += char(i + '0');
			rs += t;
		}
	}
	return rs;
}

template<typename T1, typename T2>
inline bool equ(T1 t1, T2 t2) { return t1 == (T1) t2; }

int main()
{
	string num;
	while (cin>>num && !equ(num[0], '-'))
	{		
		int c = 0;
		string N = num;
		map<string, int> mapS_i;
		while (true)
		{
			mapS_i[num] = c;
			string t = countNum(num);

			if (equ(t, num))	//self-inventory
			{
				if (equ(0, c))
				{
					cout<<N<<" is self-inventorying\n";
				}
				else
				{
					cout<<N<<" is self-inventorying after "
						<<c<<" steps\n";
				}
				break;
			}
			else if (mapS_i.count(t))	//loop-inventory
			{
				int L = c - mapS_i[t] + 1;//易错处:What's loop of length?!
				cout<<N<<" enters an inventory loop of length "<<L<<"\n";
				break;
			}
			else if (c >= 14)//易错处:写成15就错!
			{
				cout<<N<<" can not be classified after 15 iterations\n";
				break;
			}

			num = t;
			c++;
		}
	}
	return 0;
}


20151-20更新一下程序,逻辑稍微整洁一点。

void coutNum(char *rs, char *num)
{
	short n = strlen(num);
	short hashNum[10] = {0};
	for (short i = 0; i < n; i++)
	{
		hashNum[num[i]-'0']++;
	}
	short j = 0;
	for (short i = 0; i < 10; i++)
	{
		if (hashNum[i])
		{
			short t = hashNum[i], front = j;
			while (t)
			{
				rs[j++] = t % 10 + '0';
				t /= 10;
			}
			short back = j - 1;
			while (front < back)
			{
				char a = rs[front];
				rs[front] = rs[back];
				rs[back] = a;
				front++;
				back--;
			}
			rs[j++] = i + '0';//容易出错:注意题意,需要数上这个数字。
		}
	}
	rs[j] = '\0';//注意收尾
}

int main()
{
	char num[81], coutRes1[81], coutRes2[81];	
	while (gets(num) && num[0] != '-')
	{
		strcpy(coutRes1, num);
		char *pc1 = coutRes1, *pc2 = coutRes2;
		map<string, short> mpStrInt;
		short c = 0;
		for (; c < 15; c++)
		{
			mpStrInt[pc1] = c;
			coutNum(pc2, pc1);
			if (mpStrInt.count(pc2))
			{
				short len = c - mpStrInt[pc2];
				if (!c && !len)
				{
					printf("%s is self-inventorying \n", num);
					break;
				}
				else if (!len)
				{
					printf("%s is self-inventorying after %d steps\n",
					num, c);
					break;
				}
				else
				{
					printf("%s enters an inventory loop of length %d \n",
						num, len+1);
					break;
				}
			}
			char *t = pc1;
			pc1 = pc2;
			pc2 = t;
		}
		if (!(c ^ 15))
		{
			printf("%s can not be classified after 15 iterations\n", num);
		}
	}
	return 0;
}





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值