P2602 [ZJOI2010]数字计数&P1239 计数器&P4999 烦人的数学作业
P2602 [ZJOI2010]数字计数
题解
DFS 恶心的数位DP
对于这道题,我们可以一个数字一个数字的求
也就是分别统计区间 [ L , R ] 内部数字 i 出现的次数 (0<=i<=9)
也就是DFS只需要记录 :
当前填到第几位 pos
k一共出现多少次 sum
目标数字 k
是否顶上界 limit
是否全是前导零 qdl
dp[pos][sum]:
>不顶上界,没有前导零,
当前填到第pos位,目标数字一共出现sum次的时候(前pos位中一共有sum个目标数字)
对答案产生的贡献
>由于sum最多会取到和pos一样的个数,所以数组大小开的和pos一样就好了
这里 sum 记录的时候分两种情况:
(1)k!=0 直接看看 所填数字是否目标数字 就好了
(2)k=0 <1> 前面全是前导零,但是所填数字不是0
<2> 填到最后数字是0,也就是0000000,此时0要算出现一次
<3> 其余情况就不记录0出现的次数了
代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<queue> using namespace std; typedef long long ll; inline ll read()
{
ll ans=;
char last=' ',ch=getchar();
while(ch<''||ch>'') last=ch,ch=getchar();
while(ch>=''&&ch<='') ans=ans*+ch-'',ch=getchar();
if(last=='-') ans=-ans;
return ans;
} ll a,b;
ll c[],len;
ll dp[][]; ll dfs(ll pos,ll sum,ll k,bool limit,bool qdl)
{
if(pos<=) return sum;
if(!limit&&!qdl&&dp[pos][sum]!=-) return dp[pos][sum];
ll ans=;
ll up=limit?c[pos]:;
for(int i=;i<=up;i++)
ans+=dfs(pos-,sum+(k==?(!qdl&&i==)||(qdl&&i==&&pos==):(i==k)),k,limit&&(i==up),qdl&&(i==));
if(!limit&&!qdl) dp[pos][sum]=ans;
return ans;
} ll sum(ll x,ll k)
{
memset(c,,sizeof(c));len=;
memset(dp,-,sizeof(dp));
while(x)
{
c[++len]=x%;
x/=;
}
return dfs(len,,k,,);
} int main()
{
a=read();b=read();
for(int i=;i<=;i++)
printf("%lld ",sum(b,i)-sum(a-,i)); return ;
}
双倍经验(比第一个简单)
P1239 计数器
题解
也就是只需要一个 a 就够够的了
代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<queue> using namespace std; typedef long long ll; inline ll read()
{
ll ans=;
char last=' ',ch=getchar();
while(ch<''||ch>'') last=ch,ch=getchar();
while(ch>=''&&ch<='') ans=ans*+ch-'',ch=getchar();
if(last=='-') ans=-ans;
return ans;
} const ll mod=1e9+;
ll a,b,T,ans=;
ll c[],len;
ll dp[][]; ll dfs(ll pos,ll sum,ll k,bool limit,bool qdl)
{
if(pos<=) return sum;
if(!limit&&!qdl&&dp[pos][sum]!=-) return dp[pos][sum];
ll ans=;
ll up=limit?c[pos]:;
for(int i=;i<=up;i++)
ans+=dfs(pos-,sum+(k==?(!qdl&&i==)||(qdl&&i==&&pos==):(i==k)),k,limit&&(i==up),qdl&&(i==));
if(!limit&&!qdl) dp[pos][sum]=ans;
return ans;
} ll sum(ll x,ll k)
{
memset(c,,sizeof(c));len=;
memset(dp,-,sizeof(dp));
while(x)
{
c[++len]=x%;
x/=;
}
return dfs(len,,k,,);
} int main()
{
a=read();
for(int i=;i<=;i++)
printf("%lld\n",sum(a,i));
return ;
}
三倍经验
P4999 烦人的数学作业
题解
拿题一看:我要AC辣!!!
现实是 90pt
为哈!!!!!!
取模的锅,多取几次

我还是太天真
代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<queue> using namespace std; typedef long long ll; inline ll read()
{
ll ans=;
char last=' ',ch=getchar();
while(ch<''||ch>'') last=ch,ch=getchar();
while(ch>=''&&ch<='') ans=ans*+ch-'',ch=getchar();
if(last=='-') ans=-ans;
return ans;
} const ll mod=1e9+;
ll a,b,T,ans=;
ll c[],len;
ll dp[][]; ll dfs(ll pos,ll sum,ll k,bool limit,bool qdl)
{
if(pos<=) return sum;
if(!limit&&!qdl&&dp[pos][sum]!=-) return dp[pos][sum];
ll ans=;
ll up=limit?c[pos]:;
for(int i=;i<=up;i++)
ans+=dfs(pos-,sum+(k==?(!qdl&&i==)||(qdl&&i==&&pos==):(i==k)),k,limit&&(i==up),qdl&&(i==));
if(!limit&&!qdl) dp[pos][sum]=ans;
return ans;
} ll sum(ll x,ll k)
{
memset(c,,sizeof(c));len=;
memset(dp,-,sizeof(dp));
while(x)
{
c[++len]=x%;
x/=;
}
return dfs(len,,k,,);
} int main()
{
T=read();
while(T--)
{
ans=;
a=read();b=read();
for(int i=;i<=;i++)
{
ll tmp=((sum(b,i)-sum(a-1,i))%mod+mod)%mod; ans=((ans+i*tmp%mod+mod)%mod+mod)%mod;
} printf("%lld\n",ans%mod);
} return ;
}
P2602 [ZJOI2010]数字计数&P1239 计数器&P4999 烦人的数学作业的更多相关文章
- [洛谷P4999]烦人的数学作业
题目大意:定义$f(x)$表示$x$每一个数位(十进制)的数之和,求$\sum\limits_{i=l}^rf(i)$,多组询问. 题解:数位$DP$,可以求出每个数字的出现个数,再乘上每个数字的大小 ...
- P2602 [ZJOI2010]数字计数(递推)
P2602 [ZJOI2010]数字计数 思路: 首先考虑含有前导0的情况,可以发现在相同的\(i\)位数中,每个数的出现次数都是相等的.所以我们可以设\(f(i)\)为\(i\)位数每个数的出现次数 ...
- 数位dp详解&&LG P2602 [ZJOI2010]数字计数
数位dp,适用于解决一类求x~y之间有多少个符合要求的数或者其他. 例题 题目描述 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除 ...
- 洛谷P2602 [ZJOI2010]数字计数 题解 数位DP
题目链接:https://www.luogu.com.cn/problem/P2602 题目大意: 计算区间 \([L,R]\) 范围内 \(0 \sim 9\) 各出现了多少次? 解题思路: 使用 ...
- luoguP4999 烦人的数学作业
写在前面 这两天信息量有点大,需要好好消化一下,呼呼 \(f[i][j]\) 的转移式还是好理解的,但是对于其实际意义课上有点糊 求 \(ans_{1, x}\) 是感觉手动把数拆开看会好理解一点?? ...
- 洛谷P2602 [ZJOI2010]数字计数(数位dp)
数字计数 题目传送门 解题思路 用\(dp[i][j][k]\)来表示长度为\(i\)且以\(j\)为开头的数里\(k\)出现的次数. 则转移方程式为:\(dp[i][j][k] += \sum_{t ...
- Luogu P2602 [ZJOI2010]数字计数
这算是一道数位DP的入门题了吧虽然对于我来说还是有点烦 经典起手式不讲了吧,\(ans(a,b)\to ans(1,b)-ans(1,a-1)\) 我们首先预处理一个东西,用\(f_i\)表示有\(i ...
- P2602 [ZJOI2010]数字计数
https://www.luogu.org/problemnew/show/P2602 数位dp #include <bits/stdc++.h> using namespace std; ...
- 洛谷 P2602 [ZJOI2010]数字计数
洛谷 第一次找规律A了一道紫题,写篇博客纪念一下. 这题很明显是数位dp,但是身为蒟蒻我不会呀,于是就像分块打表水过去. 数据范围是\(10^{12}\),我就\(10^6\)一百万一百万的打表. 于 ...
随机推荐
- 升级openssh到高版本
linux升级openssh到高版本 可以解决OpenSSH 安全漏洞(CVE-2018-15919)和SSH服务器类型和版本 如果是新服务器,需要安装对应命令vim 上传下载等命令 安装上传或者下载 ...
- LED点阵显示
/*********************************************************** 8*8LED点阵---显示数字实验 实现现象:下载程序后点阵上显示数字0 注意 ...
- LintCode上的一道算法面试题: 数字的统计
说到数字的统计,小时候的数学课大家都应该有学过,但数字太多太复杂的,手动肯定耗时间不说还很容易出错.所以今天分享一下如何用程序来完成. Have you met this question in a ...
- Tomcat - Tomcat安装
Tomcat官网:http://tomcat.apache.org/ 准备:JAVA环境布置完成 一.Windows平台 1. 版本选择 1) 进入官网 2) 查看版本匹配 官网说明 https:// ...
- TCP 的三次握手和四次挥手,TCP 的流量控制和拥塞控制
70.TCP协议的三次握手与四次挥手70.1.TCP报文结构 1.源端口号:表示发送端端口号,字段长为16位. 2.目标端口号:表示接收端口号,字段长为16位. 3.序列号:表示发送数据的位置 ...
- Linux权限操作(用户和组)
useradd 添加用户useradd -u uid user 创建指定uid的用户-o 配合-u 不检查uid的唯一性-d 指定家目录-s 指定shell-r 创建系统用户-m 强制创建家目录-M ...
- [NOI2008]假面舞会——数论+dfs找环
原题戳这里 思路 分三种情况讨论: 1.有环 那显然是对于环长取个\(gcd\) 2.有类环 也就是这种情况 1→2→3→4→5→6→7,1→8→9→7 假设第一条链的长度为\(l_1\),第二条为\ ...
- Java项目笔记01
1 Tomcat问题 1 今天用了Ecplise和MyEcplise想着用同一个路径下的Tomcat,但是却发现配置完Ecplise后MyEcplise却不能用了,并且后面在bin里启动Tomcat还 ...
- gcc/g++以c++11编译
方法一: //在程序头加上预定义编译器命令 #pragma GCC diagnostic error "-std=c++11" //通过#pragma 指示 GCC编译器处理错误的 ...
- kubernetes 之部署metrics-server v0.3.1
Metrics-server简介 Metrics-server是用来替换heapster获取集群上资源指标数据的,heapster从1.11开始逐渐被废弃了. 在使用heapster时,获取资源指标是 ...