分治算法-计算问题

题目:本题要求出 1 在两个数 a 和 b 之间出现的次数。可以用分治算法的思想,先求出 1 在 0~a 之间出现的次数,再求出 1 在 0~b 之间出现的次数,然后两者相减即可。现在的问题是如何求出 1 在 0~a 之间出现的次数。将 0~197 的数列列出后可以看出规律:
可以求出 1 在 190~197 之间出现的次数,然后考虑 1 在 0~189 之间出现的次数。190~197 中 1 在各位上出现了1 次。
个位考虑完后,直接考虑 197/10-1 (即18)中出现的次数,同时考虑,数字减小了,每一位的权值会增加,也就是说每一个数字出现的次数会增加 10 倍。

例如,现在的 1,是原来的 10~19 之间的所有的 1 ,即权值变为了原来的 10 倍。输入要求:输入不会超过500行。每行输入两个数a和b,a和b的范围是:0~100 000 000。输入两个0时程序结束。详见输入样例。输出要求:对于每一对输入的a和b,输出一个数,表示1出现的个数。详见输出样例。输入输出样例:
输入
1 10
44 497
346 542
1199 1748
1496 1403
1004 503
1714 190
1317 854
1976 494
1001 1960
0 0
Output sample:
2
185
40
666
113
105
1133
512
1375
1256

/注释以计算0~197之间各数出现次数的概率为例/```
#include
using namespace std;
//
const int N = 11;
void deal(int n);
int value;
int d[N]; //这里的d[n],存储0~9在两个数之间出现的次数,输出时只要输出d[1];就好了
/
/
void deal(int n) //注释以197为例;
{
if(n<=0)return;
int one,ten;
one = n%10;
n/=10;
ten = n;
int i;
for (i=0;i<=one;i++) //个位出现各个数的次数;
{
d[i]+=value;
}
while (ten) //记10位和百位上分别出现9,1时,9,1,
//出现的次数,因为当前两位是19时,1,9的权值
//要分别加上one+1;
{
d[ten%10]+=(one+1)value;
ten/=10;
}
for(i =0;i<10;i++) //算前两位为0~18时个位出现的不同数的个数,并跟之前的相加;
d[i]+=value
n;
d[0]-=value; //前两位不能为0
value
=10;
deal(n-1);

}
int main()
{
int a,b,i ;
int tmp;
while(cin>>a>>b)
{
if(a0&&b0)
{
cout<<“pay attention to your input”<<endl;
break;
}
if(a<b)
{
tmp=a;a=b;b=tmp; //将较大的值存入a中,较小的存入b;
}
for(i=0;i<10;i++)
d[i]=0;
/************************************************/
value =1;
deal(a);
value = -1; //为了求出deal(a)-deal(b);
deal(b-1);
cout<<d[1]<<endl;
}
return 0;

}



运行界面:
![这里写图片描述](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcwMzExMjA0OTI1ODQ1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值