从数字1~n中存在几个字符m(c语言)

博客讨论了如何优化计算在给定范围[m, n]内数字n出现的次数的算法。原代码通过遍历和逐位检查实现,而优化后的代码利用数学规律和位运算大幅提高了效率。优化思路包括获取高位的基础值和根据本位计算修正值。新代码通过循环和位操作,减少了不必要的计算,提升了运行速度。
摘要由CSDN通过智能技术生成

目录

                原思路

                原代码

                思路优化

                优化代码


问题意思是输入两个数字,m,n,从1到m中,数字n出现的次数,例如输入11,1。1~11中1总共出现了4次。

原思路:从1开始进入循环,若m处于1到9之间,当n==i时,定义计数器temp+1.若m大于9,则进行求每一位数字,方法如下:首先用i对10取余,得到个位,然后i/10,然后再次取余,得到十位,循环下去得到每一位数字,循环停止条件为i的值为0.在循环中加入判断条件,如果取余的结果(每个位上的数字)等于你,则计数器加一。此处数字位数的循环应在循环外进行标记,因为循环结束的条件位i==吗,若不加标记,则循环无法结束。

源代码:

int vs(int m, int n)
{
	int p=0;//计数器
	int vlan;//标记
	for (int i = 1; i<=m; i++)
	{
		vlan = i;
		if (i == n) p++;
		else {
			while (i != 0)
			{
				if (i % 10 == n) p++;//余数(每一位数字)等于n,计数器加一
				i /= 10;
			}
			i = vlan;//循环结束之后i会变为0,需要利用标记进行重新赋值
		}
	}
	return p;
}

int main()
{
	int m, n;
	scanf("%d", &m);
	scanf("%d", &n);
	int p=vs(m, n);
	printf("%d", p);
}

思路优化:以上代码位最普遍的思路,强行进行计算求和,不建议使用。优化思路如下:

最简单的方式就是利用公式求在各位,十位,百位上的出现次数,然后求和便是想要的结果。首先要知道规律:1~10之间出现数字次数位1,1~100之间出现次数为10,1~1000出现次数为100,很显然可以看出规律1~(10^i)中出现数字n的次数为(10^(i-1));有了这个规律,接下来就很简单。我们首先用举例,然后再例子中找规律。

我们以在1~3657中找6为例,

个位开始计算,高位是365(3657/10),此时1~3650中,出现6的次数为高位*1,即365,然后看本位,即7,因为7>6,1~7中只能存在一个6,所以+1,结果为365+1=366;

其次是十位,高位是36(3657/100),此时1~3600中出现6的次数为高位*10,即360,本位为5,因为5<6,所以不做计算,结果为360;

接着是百位,高位为3,(3657/1000),此时1~3000中6出现的次数为高位*100,即300,本位为6,因为6==6,所以此处3000~3657中6出现的次数肯定不够60(6*10),应该这么算57+1(57为低位),低位+1.所以结果是58+300=358.

最后是千位,无高位,本位为3,3<6,所以此处无6,

最终结果为366+360+358=1084.

我们可以找到规律,

1)取基础值,首先应该取高位数字即(m/(10^(i+1))),此处i为位数(个位 0,十位 1...),若存在高位,即计数器加高位*(10^(i+1)),若不存在则为0,基础值便是高位*(10^(i+1)。

2)取修正值,即用本位(m)和要查找的数字(n)作比较,

        当m>n时,修正值为(10^i),

        当m==n时 直接带入公式,低位+1

        当m<n时,无修正值。

优化代码:

int vs(int n, int x)
{
	int count=0, k;
	for (int i = 1; k = n/i; i *= 10)
	{//k/10为高位
		count+=( k / 10)*i;
		int  m= k % 10;//当前位的数
		if (m > x) 
		{ 
			count += i;
		}
		else if (m == x)//低位+1
		{
			count += n - k*i + 1;//(n-k*i)为低位
		}

	}
	
	return count;
}

int main()
{   int m,n;
	scanf("%d", &m);
	scanf("%d", &n);
	int p=vs(m, n);
	printf("%d", p);
}

循环的节指条件便是本位为0,很显然这段代码比较与原来的代码,运算效率提高了很多,建议使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

*闲鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值