1出现的次数

今天我在比赛的时候遇见一个神奇的问题,让我们求从1-n中包含多少个1

这个题简单爆了啊!!!

在没看到数据前我也是这么认为的……

emm,这个会TLE吧(只有一秒时限)

不能用简单无脑的模拟了(毒瘤题目害人啊)

让我们来转换一下思路,如果一直把一位固定,那一共有多少种情况呢?

来定义3个变量辅助思考吧;

q,z,h(前,中,后)

还有一个f(固定位置的单位,比如个,十,百,千……)

q是说这个数的固定位置的前面是几;

z是说这个数的固定位置是几;

h是说这个数的固定位置的后面是几;

这个这个,如果我们固定的位置是0,那么固定这一位有1的情况就有qf种,大家说对不对啊~

哎呀知道你们不会~(要是会就不来了)

来我分析一下,他前面有0~q-1(这一位是0了,如果前面是q后面就没啥用了)个数,每个都可以在后面有f个数,所以就是qf。

比如1204,我们把0那个位置设定为固定位置,0前面有12种(0,1,2,3,4,5,6,7,8,9,10,11),后面有10种可能(0,1,2,3,4,5,6,7,8,9),然后就有12*10种组合。

听懂了吧~

(再听不懂我也没办法了QWQ)

然后是第二种情况,固定位置等于1的情况:

等于1和等于0其实没啥区别,微弱的区别是等于1时后面的数可以和前面的组合(当然仅限于前面是q),所以啊,我们可以轻松的找到计算公式,就是qf+h+1(带着0)啊。

和谐的知识增加了~

接下来就是第三种了,第三种就是固定位置上的数是大于1的:

哎呀还是一样不难,大于1的话表示前置q的情况已经全部有用,也就是可以多算一个f啦,我们利用乘法结合律把他合并成一个公式,哦豁,就是(q+1)*f。

这样一来,3种情况我们都已经推出来了,直接把每一位上面的数加在一起就好了对吧。来,上代码吧。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
using namespace std;
long long f=1,n,m,zshu;
long long q,h,z;
int main()
{
	cin>>n;
	while(n>=f)
	{
		q=n/(f*10);//获取固定位置前面的数 
		h=n%f;//获取固定位置的数 
		z=n/f%10;//获取固定位置后面的数 
		if(z==0)//情况1 
		{
			zshu+=q*f;//有q*f个可能性。 
		}else if(z==1)//情况2
		{
			zshu+=q*f+h+1;//q*f+h+1个可能性 
		}else//情况3 
		{
			zshu+=(q+1)*f;//情况3就是(q+1)*k个可能性啊 
		}
		f*=10;//继续固定下一位 
	}
	cout<<zshu<<endl;//嗯嗯,完美的结束了 
	return 0;
}

哎呀呀,我靠一己之力做出了最不擅长的数论,这说明(摘自某个r姓大佬的说说)(鸡汤走起)

posted @ 2020-06-27 19:59  lichangjian  阅读(269)  评论(2编辑  收藏  举报