统计区间[a,b]各个数字出现的个数:poj 2282 The Counting Problem poj 3286
来源:互联网 发布:windows2008内存优化 编辑:程序博客网 时间:2024/05/20 00:17
组合数学中体现分析功底的基础题
题目大意
给定一个区间[a,b],统计区间内0,1,2,3,4,5,6,7,8,9各个数字出现的个数。
解题思路
问题转化为(0,n】区间各个数字出现的个数(最后用b减去a-1就是结果),关键是怎样去计数呢?
举个例子大家就会非常明白,以2345为例,分区间
————
0 0 0 1
…
1 0 0 0
…
2 0 0 0
————
2 0 0 1
…
2 3 0 0
————
2 3 0 1
…
2 3 4 0
————
2 3 4 1
…
2 3 4 5
————
第一个区间,先取得最高位2,高位上的0,1出现的次数为1000次,而2出现的次数是000~345,即346次;再看低位000~999,0~9出现的次数是相同的3*1000/10,高位0,1决定最终结果×2,即0~9次数加上2×3×1000/10;
注意这一步多考虑了前导零,而且只有在这一步,接下来的区间内并不会出现前导零,所以可以先不用管,等把所有区间都解决了,最后再减去前导零。
接下来分析第二个区间2001~2300.同样地,先取得最高位3(此时2的所有情况在第一个区间已经计数完毕,最高位已经失去意义),从001~300,高位上0,1,2出现的次数是100次,(0不是前导零啦!),低位00~99中0~9各出现3×2×100/10,分别计数;
以此类推至第3、4区间2301~2340,2341~2345,循环处理相同。
最后,不要忘记把多算的前导零减去,千位上的0多算了1000次,百位100,视为10,个位1,即最后减去1000+100+10+1
参考代码+部分解释
#include <iostream>#include <cstdio>#include <algorithm>#include <map>#include <vector>#include <cstring>#include <cmath>using namespace std;typedef long long ll;const int maxn = 7e4+10;int a,b,f[10]={0},g[10]={0};void swap(int &a,int &b){int temp=a;a=b;b=temp;return;}void solve(int n,int *h)//计算(0,n]区间0123456789出现的次数,记录在数组f[]中,以2345为例{ if(n==0) return; int m=n,len=0;while(n){len++;n/=10;};n=m; //得到长度len,用m恢复n for(int i=len;i>0;i--){ //从高位向低位一个一个处理 int temp=(int)pow(10.0,i-1),digit=n/temp; //取高位digit //处理高位 for(int j=0;j<digit;j++) h[j]+=temp;h[digit]+=n%temp+1; int res=digit*(i-1)*temp/10;for(int i=0;i<10;i++) h[i]+=res; n%=temp; } for(int i=len;i>0;i--) h[0]-=(int)pow(10.0,i-1);//对多余0的处理 return;}int main(){ // freopen("input.txt","r",stdin); while(cin>>a>>b&&a+b){ memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); if(a>b) swap(a,b); solve(a-1,f); solve(b,g); for(int i=0;i<10;i++) if(i) cout<<" "<<g[i]-f[i];else cout<<g[i]-f[i]; cout<<endl; } return 0;}
poj 3286: How many 0’s?买一送一~
题目大意
统计区间[a,b]中数字0出现的个数
解题思路
是poj2282的一部分,解题思路是一样的,但是发现了poj2282算法中的一出问题(浮点数精度误差),强制转换double为int会有误差的,比如temp=100,实际会生成99,所以在这里我重新定义了一个变量x记录1000->100->10->1,避免了浮点数误差问题。
还要要注意的是开始区间m=0的问题,m-1是-1,求出来的结果与实际不符,所以我还是特判了一下m=0的情况,从1开始的仍然按照上一道题的处理方法解决。
参考代码
#include <iostream>#include <cstdio>#include <algorithm>#include <map>#include <vector>#include <cstring>#include <cmath>using namespace std;typedef long long ll;const int maxn = 7e4+10;ll m,n;ll solve(ll n)//计算(0,n]区间0出现的次数,记录在ans中{ ll ans=0; ll m=n,len=0,x=1;while(n){len++;n/=10;x*=10;};n=m; //得到长度len,用m恢复n for(ll i=len;i>0;i--){ //从高位向低位一个一个处理 x/=10;int temp=x,digit=n/temp; //取高位digit //处理高位 if(digit>0) ans+=temp;else ans+=n%temp+1; ll res=digit*(i-1)*temp/10;ans+=res; n%=temp; } x=1; for(int i=0;i<len;i++) {ans-=x;x*=10;}//对多余0的处理 return ans;}int main(){ // freopen("input.txt","r",stdin); while(cin>>m>>n&&(m>=0)){ if(m==0) cout<<solve(n)+1<<endl; else cout<<solve(n)-solve(m-1)<<endl; } return 0;}
- 统计区间[a,b]各个数字出现的个数:poj 2282 The Counting Problem poj 3286
- (Realx 数论1.28)POJ 2282 The Counting Problem(区间统计数字:统计a、b之间各个数字(0~9)出现的次数)
- Poj 2282 The Counting Problem[统计区间 0 - 9出现的次数]
- POJ 2282-The Counting Problem(组合数学_区间计数)
- poj 2282 The Counting Problem 按位统计
- poj 2282 The Counting Problem
- POJ-2282-The Counting Problem
- [POJ] 2282 -> The Counting Problem
- POJ 2282 The Counting Problem
- POJ 2282 The Counting Problem
- POJ 2282 The Counting Problem,组合数学
- The Counting Problem - POJ 2282 数位dp
- poj 3368 统计区间出现次数最多数个数 RMQ
- (Relax 数论1.29)POJ 3286 How many 0's?(统计a-b之间-出现的次数)
- POJ 2282 The Counting Problem & POJ 3286 How many 0's?(按位计算贡献)
- poj 2282 The Counting Problem && poj 3286 How many 0's? (数位dp)
- POJ题目2282 The Counting Problem(数学)
- POJ 2282 && HDU 1663 The Counting Problem(数论)
- [Java]转知乎,一处编译,到处运行?
- IO流的概念及使用方法三
- 一个golang推送服务器集群:gopush-cluster
- hdu 2111 Saving HDU
- HDU 2059 龟兔赛跑
- 统计区间[a,b]各个数字出现的个数:poj 2282 The Counting Problem poj 3286
- DEMON进程+inotify自动生成系统级文件操作日志demo
- 冒泡,插入,归并排序
- stringstream中的.clear()和.str()
- android ndk jni 编程入门例子
- Golang适合高并发场景的原因分析
- HDU1213 How Many Tables【并查集】
- 《HTTP权威指南》读书笔记(3)-HTTP连接管理及对TCP性能的考虑
- Apache 文件根目录设置修改方法 (Document Root)