51nod1042
两个数a,b(1 <= a <= b <= 10^18)
输出共10行,分别是0-9出现的次数
10 19
1
11
1
1
1
1
1
1
1
1
思路:用记忆化搜索做,当计算0的数量是要特别注意
代码
#include<stdio.h>
#include<string.h>
#define ll long long
ll dis[12];//记录位数
ll lg,len;
ll s[25];//表示10的i次方
ll ans1[12];//记录答案
ll dp[25][15][2];
ll check(ll a){ //计算分解后的前a位的值
ll i=0;
ll ans=0;
for(i=0;i<=a;i++)
ans+=dis[i]*s[i];
return ans;
}
ll dfs(ll pos,ll lg,ll k){//计算1---9的数量
if(pos<0)
return 0;
ll num=lg?dis[pos]:9;
if(!lg&&dp[pos][k][lg]!=-1)//只有没有限制的时候才能用记忆化记录的结果
return dp[pos][k][lg];
ll i,j;
ll ans=0;
for(i=0;i<=num;i++){
if(i==k){//当i等于k时,当前有k的数量就要加上后面所有可能的数字的个数 (假设是542123,当前面已经遍历完542这三位时,
//当遍历到第四位且第四位为1时,1的数量就等于23中1数量+23)
if(lg&&i==num)//注意,前面的限制不一定能对后面的计算产生影响,要看当前的i是否可以继续产生限制。
ans=ans+check(pos-1)+1+dfs(pos-1,lg&&(i==num),k);//假设是542123这个数字,当取后三位是,一共有123+1种情况(0---123)
else
ans=ans+s[pos]+dfs(pos-1,lg&&(i==num),k);// 假设是542123,当前面已经遍历到541这三位时,
//当遍历到第四位且第四位为1时,1的数量就等于100中1数量+100)
}
else
ans+=dfs(pos-1,lg&&(i==num),k);
}
if(!lg)
dp[pos][k][lg]=ans;
return ans;
}
ll dfs1(ll pos,ll lg,ll lg1){//计算零的数量
if(pos<0)
return 0;
if(!lg&&!lg1&&dp[pos][0][lg]!=-1)//只有当没有限制并且前面有非零数字时,才能用到记忆化保存的数据
{
return dp[pos][0][lg];
}
ll num=lg?dis[pos]:9;
ll i,j;
ll ans=0;
//printf("%d\n",num);
//printf("pos=%d\n",dis[pos]);
for(i=0;i<=num;i++){
//prllf("c=%d %d\n",pos,i);
if(!lg1&&i==0){
if(lg&&i==num)//注意,前面的限制不一定能对后面的计算产生影响,要看当前的i是否可以继续产生限制,在这里连续卡了几次,以为自己考虑了,但是还是没有考虑,以后做题一定要注意。
{
//printf("a=%d %d %d\n",pos,i,cal(pos)+1);
ans+=check(pos-1)+1;//同上
}
else
{
ans+=s[pos];
//printf("b=%d\n",s[pos]);
} }
//printf("%d %d %d\n",pos,i,ans);
ans+=dfs1(pos-1,lg&&(i==num),lg1&&(i==0)); }
if(!lg&&!lg1)//记忆化没有限制并且前面有非零数字的情况
dp[pos][0][lg]=ans;
return ans;
}
int main(){
ll n,m;
len=0;
scanf("%lld%lld",&n,&m);
ll i;
s[0]=1;
for(i=1;i<=18;i++)
s[i]=s[i-1]*10;
n=n-1;
while(n){//分解数字
dis[len++]=n%10;
n=n/10;
}
memset(dp,-1,sizeof(dp));
ans1[0]=-dfs1(len-1,1,1);
//printf("%d\n",ans1[0]);
for(i=1;i<=9;i++){
ans1[i]=-dfs(len-1,1,i);
}
len=0;
while(m){
dis[len++]=m%10;
m=m/10;
}
ans1[0]+=dfs1(len-1,1,1);
printf("%lld\n",ans1[0]);
for(i=1;i<=9;i++){
ans1[i]+=dfs(len-1,1,i);
printf("%lld\n",ans1[i]);
} return 0;
}
51nod1042的更多相关文章
- 【51nod-1042】数字0-9的数量
给出一段区间a-b,统计这个区间内0-9出现的次数. 比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次. Inp ...
- 51nod1042(0-x出现次数&分治)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1042 题意:中文题诶- 思路:这道题和前面的51nod100 ...
随机推荐
- 机器学习基石(台湾大学 林轩田),Lecture 2: Learning to Answer Yes/No
上一节我们跟大家介绍了一个具体的机器学习的问题,以及它的内容的设定,我们今天要继续下去做什么呢?我们今天要教大家说到底我们怎么样可以有一个机器学习的演算法来解决我们上一次提到的,判断银行要不要给顾客信 ...
- Nested Comment Treads in ROR
建立一个嵌套的评论 建立数据库结构和嵌套视图(使用Stimulus取元素和绑event) 可以删除评论,可以对嵌套视图的层数进行控制. 用Ajax代替完全的刷新页面. 删除一个评论,但不丢失它的子评论 ...
- Linux虚拟机安装VMware Tools
选择虚拟机-->install VMware Tools # 新建一个文件夹用来挂载光驱 mkdir /mnt/cdrom # 挂载光驱到指定文件夹 mount /dev/sr0 /mnt/cd ...
- Huffman Coding
哈夫曼树 霍夫曼编码是一种无前缀编码.解码时不会混淆.其主要应用在数据压缩,加密解密等场合. 1. 由给定结点构造哈夫曼树 (1)先从小到大排序(nlogn) (2)先用最小的两个点构造一个节点,父节 ...
- ActiveMQ的学习整理(代码实现PTP,以及Pub/Sub)
(一)由于在实习过程中需要用到ActiveMQ,在网上看了很多文章,现在整理出来以防忘记. (二)这篇文章比较适合之前没有接触过的同学,在看下面文章的过程中,建议先学习参考链接中的知识点,然后自己再参 ...
- zsh切换bash bash切换zsh
切换bash(需要sudo) chsh -s /bin/bash 切换zsh(不需要sudo) chsh -s /bin/zsh 注意:如果输入命令和密码后提示:no change made. 请加上 ...
- 把url链接转换成二维码的工具类
import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io ...
- python-flask-session和scoped_session区别
scoped_session from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from sql ...
- python 绝版线程池
2.绝版线程池设计思路:运用队列queue a.队列里面放任务 b.线程一次次去取任务,线程一空闲就去取任务 import queueimport threadingimport contextlib ...
- rac 关库 启库
关库顺序 先关闭数据库 然后关闭节点资源 [root@rac1 ~]# srvctl stop database -d prod[root@rac1 ~]# srvctl stop inst ...