给出一段区间a-b,统计这个区间内0-9出现的次数。

 
比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次。
Input
两个数a,b(1 <= a <= b <= 10^18)
Output
输出共10行,分别是0-9出现的次数
Input示例
10 19
Output示例
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的更多相关文章

  1. 【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 ...

  2. 51nod1042(0-x出现次数&分治)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1042 题意:中文题诶- 思路:这道题和前面的51nod100 ...

随机推荐

  1. vs2013添加mysql对EF的支持(转+说明)

    在vs2013中使用mysql连接entityFramework经常会遇到这个问题:您的项目引用了最新实体框架:但是,找不到数据连接所需的与版本兼容的实体框架数据提供程序.请退出此向导,安装兼容提供程 ...

  2. Django分页器和自定义分页器

    一.自定义分页器 import copy class Pagination(): def __init__(self,request,current_page,all_data_num,each_pa ...

  3. python记录_day06

    一.小数据池 注意大前提!!!! 小数据池只针对整数.字符串和bool值,因为这些数据是不可变的,这样数据的共享才安全 小数据池也称为小整数缓存机制或驻留机制,是指在不同代码块创建部分小数据对象(具体 ...

  4. ACM-ICPC World Finals 2019 G.First of Her Name

    题意:给一颗字典树,m次查询,每次给出一个字符串,问你该字符串是字典树上多少串的后缀 题解:字典树求广义sam,每次把查询串在sam上跑一遍,最后到达的点的sz就是答案,中途没法走了,就是没有出现过 ...

  5. img标签设置默认图片

    为了美观当网页图片不存在时不显示叉叉图片 当在页面显示的时候,万一图片被移动了位置或者丢失的话,将会在页面显示一个带X的图片,很是影响用户的体验.即使使用alt属性给出了”图片XX”的提示信息,也起不 ...

  6. hbase的wordcount

    package com.neworigin.HBaseMR; import java.io.IOException; import org.apache.hadoop.conf.Configurati ...

  7. Opatch使用细则

    Patch 21352635 - Database Patch Set Update 11.2.0.4.8 一.OPatch工具检查及升级 OPatch工具包,在安装目录$ORACLE_HOME下,P ...

  8. 7. 反转整数(Reverse Integer) C++

    知识点: 内置变量 INT_MAX   INT_MIN 运算结果是否溢出的判断 判断pop>7即pop>INT_MAX%10 判断pop<-8即pop<INT_MIN%10 c ...

  9. kdbg安装使用教程(kali)

    一.背景说明 所谓调试者,主要就是下断点.观察变量,不是太复杂的事情也不用太复杂的工具. 但具体到linux平台而言,gdb本来多敲几下命令也不是不可以的事,但是一个屏幕就那么大打印出一堆东西又乱又看 ...

  10. makefile文件写法解析

    一.makefile文件示例 makefile文件并不难写,一个makefile模版如下所示,所有makefile文件在此基上稍微修改就可以了. # this is a makefile #这一行是注 ...