BIT2014级软件学院程序设计-10 ⑨的统计

众所周知,琪露诺(チルノ,Cirno)是幻想郷 (げんそうきょう)中首屈一指的天才,可以说⑨就是她的代名词。

然而如今,她遇到了一个和⑨有关的难题。你能帮助她么?

题目是这样的,给出两个数 a 和 b (0 <= a <= b <= 10^10000),求 a 到 b 之间(包括a和b)的数字中,有多少个数字是包含9的(例如 19,910 等都是包含9的数字)。

输入

第一行为一个数字 T (0 < T <= 100) 表示数据组数。

之后的 T 行,每行包含两个数 a 和 b (0 <= a <= b <= 10^10000)。

输出

对每组数据输入,输出一个数字,表示 a到 b 之间的数字中(包括a和b),有多少个数字是包含9的。(注意:答案可能很大)

Sample Input

2

0 9

0 100

Sample Output

1

19

感觉基本应该是程设最难的一道题了把,我感觉是。

先转化成求0-a和0-b有多个数字9

数量很大要用到高精度。用数组来存数字。

然后比如13012958就是求10000000的9+3000000的9+10000的9+2000的9+958

至于10000000有多少个9就可以直接用公式了。

10:1;100:1*9+10=19;1000:19*9+100;...........................................

然后计算高精度注意一些东西就好了,比如压缩一下位数,还有应用一下秦九韶公式就好

#include<stdio.h>
#include<string.h>
#define	mod 100000000
#define maxn 10080
#define end 1300
char a[maxn];
char b[maxn];
int num[maxn];
int ans[3][end+2];//答案数组

void big_sum(int *a1, int ak)
{
	int i, k=0;
	a1[end] += ak;
	for(i=end;i>=0;i--)
	{
		if(a1[i]>=mod)
		{
			a1[i]-=mod;
			a1[i-1]++;
		}
		else break;
		//if(a1[end]>mod)
		//a1[end]-=mod;
		//a1[end-1]++;//为了节省时间复杂度没有用循环,不够严谨,可能全是999999999需要进位
}
	return;
}

void big_cheng(int *a1,int ak)
{

	int i, k;
	int j=0;
	while(!a1[j])
	j++;//j是第一位非0
	for (i = end;i>=j;i--)
		a1[i] *= ak;
	//a1[0] *= ak;
	k = 0;
	for (i = end;i>=j-2;i--)//进位
	{
		a1[i] += k;
			k = a1[i] / mod;
		a1[i] = a1[i] % mod;
	}
	return;
}
void big_jian(int *a1, int *a2, int *a3)
{
	int i;
	for (i = end;i >= 0;i--)
	{
		a1[i] = a2[i] - a3[i];
	}
	for (i = end;i >0 ;i--)
	{
		if (a1[i] < 0)
		{
			a1[i -1]-=1;
			a1[i] += mod;
		}
	}
	return;
}

void search_9(int length,int flag)//flag为0 是第一个数,1是第二个数
{//利用秦九韶算法
	int i;
	int flag9=0;
int ans1[end+5]={0};
int ans2[end+5]={0};
		ans1[end]=num[0];

		ans2[end]=num[0];
		if(num[0]==9)//判断9
		flag9=1;
	for (i = 1;i < length;i++)
	{

		big_cheng( ans1,10);//高精度乘法
		big_sum(ans1, num[i]);//高精度加法

		if (flag9)
		{
			big_cheng(ans2, 9);
		}
		else {
			big_cheng(ans2, 9);
			big_sum(ans2, num[i]);
		}
		if(num[i]==9)
		flag9=1;
	}
	big_jian(ans[flag],ans1, ans2);
	return;
}
int main()
{
	//freopen("F:in.txt","r",stdin);
//	freopen("F:out1.txt","w",stdout);

	int T;
	int la, lb;
	int i, j,flag2;
	scanf("%d", &T);
	while(T--)
	{
		flag2 = 0;
	//	memset(ans,0,sizeof(ans));
	//	memset(num,0,sizeof(num));
		scanf("%s%s", a, b);
		la = strlen(a);lb = strlen(b);
		for (i = 0;i < la;i++)
		{
			num[i] = a[i] - '0';


		}search_9(la, 0);
	//	memset(num,0,sizeof(num));
		for (i = 0;i < lb;i++)
		{
			num[i] = b[i] - '0';
			if (num[i] == 9)
				flag2 = 1;
		}

		search_9(lb,1);
		big_jian(ans[2], ans[1], ans[0]);
		ans[2][end] = ans[2][end] + flag2;

			for(i=end;i>=0;i--)
		{
			if(ans[2][i]>=mod)
			ans[2][i-1]++;
			else break;
		}


		for (i = 0;i <= end;i++)
		{
			if (ans[2][i])
				break;
		}
		printf("%d", ans[2][i]);
		i++;

		while (i <= end)
		{

			printf("%08d", ans[2][i]);
			i++;
		}
		printf("\n");
	}
	return;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值