今天我在比赛的时候遇见一个神奇的问题,让我们求从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*9种组合。
听懂了吧~
(再听不懂我也没办法了QWQ)
然后是第二种情况,固定位置等于1的情况:
等于1和等于0其实没啥区别,微弱的区别是等于1时后面的数可以和前面的组合(当然仅限于前面是q),所以啊,我们可以轻松的找到计算公式,就是qf+h啊。
和谐的知识增加了~
接下来就是第三种了,第三种就是固定位置上的数是大于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姓大佬的说说)(鸡汤走起)