题解 P4999 【烦人的数学作业】
数位 dp。
设 \(dp_{q,i}\)(\(i\in\{0,1,2,3,4,5,6,7,8,9\}\))为 \(1\sim q\) 中 \(i\) 出现的次数,\(1\sim q\) 的数字和显然就是 \(dp_{q,0}\times 0+dp_{q,1}\times 1+\cdots+dp_{q,i}\times i\cdots+dp_{q,9}\times 9\)。
所以我们只需要求出 \(1\sim q\) 中 \(i\) 出现的次数就能解决这个问题了。
这个问题看起来很好解决,但是注意前导零会影响结果,所以不能有前导零。
这该怎么办呢?
有前导零的式子很容易推出。有 \(q\) 位数字,\(i\) 数码的出现次数对于 \(x\in\{s\mid s\in \mathbb N,10^q\le s\le10^{q+1}\}\) ,\(f(q,i)\) 的数量都是相等的(设 \(f(q,i)\) 为 \(q\) 位数 \(i\) 数码的出现次数)。
具体求法罢,是:
\(\begin{cases}f(q,i)=0&q=0\\f(q,i)=10f(q-1)+10^{q-1}&q>0\end{cases}\)
我们考虑减去多余的 \(0\)。
我们先设数字为 \(\overline{A_1A_2A_3\dots A_n}\)
我们首先考虑求 \(\overline{A_100\dots 0}\),将 \(\overline{A_100\dots 0}\) 分割为区间 \([0000,1000),[1000,2000),\dots,[\overline{(A_1-1)00\dots 0},\overline{A_100\dots 0})\),所以答案就为 \(10^{n-1}A_1\),注意 \(<A_1\) 的每个数还出现了 \(10^{n-1}\) 次,所以要加上。
首位 \(A_1\) 出现了 \(\overline{A_2A_3\dots A_n}+1\) 次,答案还要加上 \(\overline{A_2A_3\dots A_n}+1\),
当然还需要处理前导 \(0\),用排列组合算一下会知道 \(i\) 位 \(q\) 个前导零的数量就是 \(10^q\)(\(q\in\{s\mid s\in\mathbb N,0\le s\le i-1\}\)),把它们加起来会发现一共出现了 \(10^{i-1}+10^{i-2}+...10\)(\(=\sum\limits_{k=0}^{i-1}10^k\)) 次,减一下即可。
Code:
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=51,MOD=1e9+7; //注意能 MOD 的地方都要 MOD,不然会 WA 0pts。
ll pow10[N],dp[N],a[N],count[N],tmpcount[N],ans;
// pow10    : 字面意思,10^n
// dp       : 不考虑前导零的状况
// count    : 统计 0~9 出现次数
// tmpcount : 暂时保存 count,用来减
// ans      : 累加答案
void init() //预处理 pow10 和 dp。
{
	pow10[0]=1;
	for (int i=1;i<30;i++) dp[i]=(dp[i-1]*10%MOD+pow10[i-1])%MOD,pow10[i]=10*pow10[i-1]%MOD;
}
void solve(ll x)
{
	int len=0;
	while (x){a[++len]=x%10;x/=10;} //数位分离
	for (int i=len;i>=1;i--)        //从高到低遍历
	{
		for (int j=0;j<10;j++) count[j]+=dp[i-1]*a[i],count[j]%=MOD;  //分割区间
		for (int j=0;j<a[i];j++) count[j]+=pow10[i-1],count[j]%=MOD; //加上 10^(n-1)
		ll lastnum=0;
		for (int j=i-1;j>=1;j--) lastnum=lastnum*10+a[j],lastnum%=MOD; //求出 A2A3A4...An
		count[a[i]]+=lastnum+1,count[a[i]]%=MOD;
		count[0]-=pow10[i-1],count[0]=(count[0]+MOD)%MOD; //减去前导零
	}
}
int main()
{
	init();
	ll l,r,T;
	cin>>T;
	for (int q=0;q<T;q++)
	{
		ans=0; cin>>l>>r;
		solve(r); //前缀和思想相减 r 和 l-1。
		for (int i=0;i<10;i++) (tmpcount[i]=count[i]),count[i]=0; //复制 count,记得清零
		solve(l-1);
		for (int i=0;i<10;i++) ans=(ans+i*(tmpcount[i]-count[i]+MOD)%MOD)%MOD,count[i]=0; //累加答案,记得清零 count。
		cout<<ans<<'\n';
	}
	return 0;
}
Refence 求数字 \(i\) 出现的次数。
题解 P4999 【烦人的数学作业】的更多相关文章
- P2602 [ZJOI2010]数字计数&P1239 计数器&P4999 烦人的数学作业
		P2602 [ZJOI2010]数字计数 题解 DFS 恶心的数位DP 对于这道题,我们可以一个数字一个数字的求 也就是分别统计区间 [ L , R ] 内部数字 i 出现的次数 (0<=i&l ... 
- [洛谷P4999]烦人的数学作业
		题目大意:定义$f(x)$表示$x$每一个数位(十进制)的数之和,求$\sum\limits_{i=l}^rf(i)$,多组询问. 题解:数位$DP$,可以求出每个数字的出现个数,再乘上每个数字的大小 ... 
- luoguP4999 烦人的数学作业
		写在前面 这两天信息量有点大,需要好好消化一下,呼呼 \(f[i][j]\) 的转移式还是好理解的,但是对于其实际意义课上有点糊 求 \(ans_{1, x}\) 是感觉手动把数拆开看会好理解一点?? ... 
- BZOJ-2326   数学作业    矩阵乘法快速幂+快速乘
		2326: [HNOI2011]数学作业 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1564 Solved: 910 [Submit][Statu ... 
- SID1190471 / 烦人的幻灯片  暴力出奇迹 !!!!!!!!!!!!!!!!!!
		PID221 / 烦人的幻灯片 ☆ 提交你的代码 查看讨论和题解 你还木有做过哦 我的状态 查看最后一次评测记录 质量还不能统计出来哦~ 题目评价 质量 无 ★★★★★ ★★★★☆ ★ ... 
- 得物(毒)APP,8位抽奖码需求,这不就是产品给我留的数学作业!
		作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ... 
- sdibt 1244 烦人的幻灯片
		在这个OJ站还没号,暂时没提交,只是过了样例 真不愧是烦人的幻灯片,烦了我一小时 ---更新:OJ测试完毕,AC 烦人的幻灯片问题 Time Limit: 1 Sec Memory Limit: 6 ... 
- bzoj2326: [HNOI2011]数学作业
		矩阵快速幂,分1-9,10-99...看黄学长的代码理解...然而他直接把答案保存在最后一行(没有说明...好吧应该是我智障这都不知道... #include<cstdio> #inclu ... 
- BZOJ 2326: [HNOI2011]数学作业( 矩阵快速幂 )
		BZOJ先剧透了是矩阵乘法...这道题显然可以f(x) = f(x-1)*10t+x ,其中t表示x有多少位. 这个递推式可以变成这样的矩阵...(不会用公式编辑器...), 我们把位数相同的一起处理 ... 
随机推荐
- spring aop 记录 service 方法调用时长 - 环绕通知
			添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sp ... 
- docker 安装和错误解决方案
			安装 x64 架构 install docker switch mirror docker desktop docker run -d -p 80:80 docker/getting-started ... 
- 48. Rotate Image - LeetCode
			Question 48. Rotate Image Solution 把这个二维数组(矩阵)看成一个一个环,循环每个环,循环每条边,每个边上的点进行旋转 public void rotate(int[ ... 
- c 语言彩票选号
			最近刚学了c语言,就做了个彩票选号程序练手玩玩,做的不好请见谅 1.分为前区(1-35)和后区(1-12)号码 2.先循环随机前区号在循环后区号 3.生成随机时数判断是否有重复值,和之前5期是否出现过 ... 
- Windows环境下启动Redis报错:Could not create server TCP listening socket 127.0.0.1:6379: bind: 操作成功完成。(已解决)
			问题描述: 今天在windows环境下启动Redis时启动失败报错: 解决方案: ①运行命令:redis-cli.exe ②退出Redis ③运行命令:redis-server.exe redis.w ... 
- AMS 新闻视频广告的云原生容器化之路
			作者 卓晓光,腾讯广告高级开发工程师,负责新闻视频广告整体后台架构设计,有十余年高性能高可用海量后台服务开发和实践经验.目前正带领团队完成云原生技术栈的全面转型. 吴文祺,腾讯广告开发工程师,负责新闻 ... 
- net core天马行空系列-可用于依赖注入的,数据库表和c#实体类互相转换的接口实现
			1.前言 hi,大家好,我是三合.作为一名程序猿,日常开发中,我们在接到需求以后,一般都会先构思一个模型,然后根据模型写实体类,写完实体类后在数据库里建表,接着进行增删改查, 也有第二种情况,就是有些 ... 
- Django 学习记录(AcWing)
			Django 2.1 搭建文件结构 前面的都是配置基本步骤,不需要理解,其他Django项目同样步骤操作: 接下来用Django-admin新建一个Django项目: django-admin sta ... 
- 陈宏智:字节跳动自研万亿级图数据库ByteGraph及其应用与挑战
			导读: 作为一种基础的数据结构,图数据的应用场景无处不在,如社交.风控.搜广推.生物信息学中的蛋白质分析等.如何高效地对海量的图数据进行存储.查询.计算及分析,是当前业界热门的方向.本文将介绍字节跳动 ... 
- 强化学习-Windows安装gym、atari和box2d环境
			安装gym pip3 install gym pip3 install gym[accept-rom-license] 安装atari环境[可选] 下载安装VS build tools 如果出现 OS ... 
