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 ...
随机推荐
- You Don't Know JS: Scope & Closures (第4章: Hoisting)
Chapter4: Hoisting 变量附加到哪个层次的scope,由它们在哪里和如何声明(let, var)来决定. Function scope/Block scope都有相同的法则:任何变量在 ...
- [LintCode] Binary Tree Level Order Traversal(二叉树的层次遍历)
描述 给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问) 样例 给一棵二叉树 {3,9,20,#,#,15,7} : 3 / \ 9 20 / \ 15 7 返回他的分层遍历结果: [ [3] ...
- HTML页面加载完毕后运行的js
Js方法:<script type=”text/javascript”> window.onload=function (){ var userName=”xiaoming”; alert ...
- Linux系统中文件定位与查找
Linux系统中文件查找 关键词 文件查找 | find | locate 本文主要介绍有关文件查找的两个命令——find和locate,以及压缩打包的命令——compress, gzip,bzip2 ...
- csu oj 1341 string and arrays
Description 有一个N*N的字符矩阵,从上到下依次记为第1行,第2行,……,第N行,从左至右依次记为第1列,第2列,……,第N列. 对于这个矩阵会进行一系列操作,但这些操作只有两类: (1) ...
- Python 3.X 要使用urllib.request 来抓取网络资源。转
Python 3.X 要使用urllib.request 来抓取网络资源. 最简单的方式: #coding=utf-8 import urllib.request response = urllib. ...
- maven生命周期绑定要点
生命周期不执行任何操作,都是抱插件大腿 maven-core-3.3.9-sources.jar下META-INF/plexus/components.xml的定义了三个生命周期的插件绑定 参考:ht ...
- 从tcp的角度看,打开一个网页到底发生了什么
使用wireshark进行抓包分析:新建表达式过滤器,选择协议,字段,匹配方式,应用就能筛选出想要的数据包. 一个示例:(tcp.srcport == 1523 or tcp.dstport == 1 ...
- npm使用过程中出现的错误
1.安装npm install axios -S报错install "npm ERR! Error: EPERM: operation not permitted" error 经 ...
- 【Loadrunner_WebService接口】对项目中的GetProduct接口生成性能脚本
一.环境 https://xxx.xxx.svc?wsdl 用户名:username 密码:password 对其中的GetProduct接口进行测试 备注:GetProducts.xml文件内容和S ...