【POJ】3720 Occurrence of Digits

感觉太久没写C代码了,打算以后有事没事就去做一做POJ,既能写代码练练手,又能提高我这弱弱的算法的能力,还能开拓思维……好处不多说啦,差点能包治百病偷笑


今天做的是3720 Occurrence of Digits:

Description

Every fraction can be converted to a repeatin decimal. For example 1/2 = .5, 1/3 = .(3) and 1/6 = .1(6). Given an integer n, Tom wants to know how many digit k occurs totally in the repeating decimal presentation of 1/2, 1/3 ... 1/n.

Input

The input consists of several test cases. Each test case is a line containing two integers (2 ≤ n ≤ 100) and k (0 ≤ k ≤ 9).

Output

Output the total occurrence of the digit.

Sample Input

3 5
7 3
7 0

Sample Output

1
1
0

该题主要是考查如何将分数转为无限循环小数的算法,在统计数字的出现频率则解决问题:

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

#define BUFFER_SIZE	128

/* 1/n(n >= 2) to repeating decimal, save in resultStr*/
int Frac2RepDec(int n, char *resultStr, int size)
{
	if (size < 2)
	{
		fprintf(stderr, "resultStr size is too small.");
		return 0;
	}
	else if (n == 1)
	{
		strcpy(resultStr, "1");
		return 1;
	}
	
	int mark[n * 10];
	int index[n * 10];
	char result[BUFFER_SIZE];
	
	memset(mark, 0, sizeof(mark));
	memset(index, -1, sizeof(index));
	memset(result, 0, sizeof(result));
	
	int i = 0, t = 10, startIndex = -1;
	int remainder = 0;
	while (1)
	{
		remainder = t % n;
		
		if (remainder == 0)
		{
			result[i++] = t / n + 48; // 转为ascii码数字
			break;
		}
		else if (mark[t])
		{
			startIndex = index[t];
			break;
		}
		
		mark[t] = 1;
		index[t] = i;
		result[i++] = t / n + 48; // 转为ascii码数字
		
		t = remainder * 10;
	}
	
	char temp[BUFFER_SIZE];
	int j = 0;
	temp[j++] = '.';
	for (i=0; result[i]>=48; ++i)
	{
		if (i == startIndex)
			temp[j++] = '(';
		temp[j++] = result[i];
	}
	if (startIndex >= 0)
		temp[j++] = ')';
	temp[j++] = 0;
	
	if (size < strlen(temp))
	{
		fprintf(stderr, "resultStr size is too small.");
		return 0;
	}
	else
	{
		strcpy(resultStr, temp);
		return 1;
	}
}

int main()
{
	char resultStr[BUFFER_SIZE];
	int count[10];
	
	int n, digit;
	int i, j;
	while (scanf("%d%d", &n, &digit) != EOF)
	{
		memset(count, 0, sizeof(count));
		for (i=2; i<=n; ++i)
		{
			if (Frac2RepDec(i, resultStr, BUFFER_SIZE))
			{
				//printf("%d/%d = %s\n", 1, i, resultStr);
				for (j=0; j<strlen(resultStr); ++j)
					if (isdigit(resultStr[j]))
					{
						++count[resultStr[j] - 48];
					}
			}
		}
		
		printf("%d\n", count[digit]);
	}

	return 0;
}

Frac2RepDec函数输出的字符串格式如下所示(1/2 , 1/3...1/20的无限循环小数):

1/2 = .5
1/3 = .(3)
1/4 = .25
1/5 = .2
1/6 = .1(6)
1/7 = .(142857)
1/8 = .125
1/9 = .(1)
1/10 = .1
1/11 = .(09)
1/12 = .08(3)
1/13 = .(076923)
1/14 = .0(714285)
1/15 = .0(6)
1/16 = .0625
1/17 = .(0588235294117647)
1/18 = .0(5)
1/19 = .(052631578947368421)
1/20 = .05



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值