【信息奥赛题解】位数问题(详细题解 C++ 代码)

news2024/11/24 5:28:00

📚 位数问题

🚀 题目浏览

【题目名称】位数问题
【题目描述】

在所有的 N N N 位数中,有多少个数中有偶数个数字 3 3 3 ? 由于结果可能很大,你只需要输出这个答案对 12345 12345 12345 取余的值。

【输入】

读入一个数 N ( N ≤ 1000 ) N(N \le 1000) N(N1000)

【输出】

输出有多少个数中有偶数个数字 3 3 3

【输入样例】
2
【输出样例】
73
【原题链接】

http://ybt.ssoier.cn:8088/problem_show.php?pid=1313


☘️ 题解分析

本题对于 算法初学者 来说有点难度,且网络上的题解都不是特别清晰,故博主撰写了本篇详细的题解分析,希望能在未来帮助到更多的同学。


首先以 N = 1 N=1 N=1,即 一位数 为例,统计一位数中 包含偶数个 3 的个数,记作 f [ 1 ] 偶 f[1]_偶 f[1] ;统计包含奇数个 3 的个数,记作 f [ 1 ] 奇 f[1]_奇 f[1]

  • 由于 0 也是偶数,所以 「0 个 3」 也满足偶数个 3 的条件,故 f [ 1 ] 偶 f[1]_偶 f[1] 为 1~2,4~9,共 8 个数(注意:0 不是一位数), f [ 1 ] 偶 = 8 f[1]_偶 = 8 f[1]=8
  • 奇数个3 的情况只有单独的 3,所以 f [ 1 ] 奇 = 1 f[1]_奇 = 1 f[1]=1

🍉 PS:有的小伙伴可能会问,题目不是求偶数的情况就够了吗?为什么要还要统计奇数的情况?继续往下看,你就明白了)


然后以 N = 2 N=2 N=2,即 两位数 为例,统计两位数中 包含偶数个 3 的个数,记作 f [ 2 ] 偶 f[2]_偶 f[2] ;统计包含奇数个 3 的个数,记作 f [ 2 ] 奇 f[2]_奇 f[2]

对于 f [ 2 ] 偶 f[2]_偶 f[2],可以分两种情况进行统计:

  • 十位为 3,则 个位必须为奇数个 3,数量为 f [ 1 ] 奇 f[1]_奇 f[1]
  • 十位不为 3(十位可以为 1~2,4~9,共 8 个数),则 个位必须为偶数个 3 ,数量为 f [ 1 ] 偶 f[1]_偶 f[1]

所以 f [ 2 ] 偶 = f [ 1 ] 奇 + 8 ∗ f [ 1 ] 偶 f[2]_偶 = f[1]_奇 + 8 * f[1]_偶 f[2]=f[1]+8f[1]

然后我们带入 f [ 1 ] 奇 f[1]_奇 f[1] f [ 1 ] 偶 f[1]_偶 f[1] ,得 f [ 2 ] 偶 = f [ 1 ] 奇 + 8 ∗ f [ 1 ] 偶 = 1 + 8 ∗ 8 = 64 f[2]_偶 = f[1]_奇 + 8 * f[1]_偶=1+8*8=64 f[2]=f[1]+8f[1]=1+88=64 ,却发现与样例答案 73 不相等。❌


这是什么原因造成的呢 ? 🧐

实际上,当我们单独拿 f [ 1 ] 奇 f[1]_奇 f[1] f [ 1 ] 偶 f[1]_偶 f[1] 讨论时,由于 0 不为一位数,所以 f [ 1 ] 偶 f[1]_偶 f[1] 为 1~2,4~9,共 8 个。

但是当 N = 2 N=2 N=2 时,由于十位上有了数字,所以此时个位上的数字是可以为 0 的,因此在计算 f [ 2 ] 偶 f[2]_偶 f[2] 时, f [ 1 ] 偶 f[1]_偶 f[1] 可以取到 0~2,4~9,共 9 个。(本质一位数个位上的数字 的区别)

同理, f [ 1 ] 奇 f[1]_奇 f[1] 也要考虑 0 的情况,但是此时 0 并不满足 「奇数个3的条件」,所以 f [ 1 ] 奇 f[1]_奇 f[1] 仍然为 1(这里 f [ 1 ] 奇 f[1]_奇 f[1] 的值虽然没有变,但是后面的 f [ 2 ] 奇 、 f [ 3 ] 奇 f[2]_奇、f[3]_奇 f[2]f[3]、…、 f [ n ] 奇 f[n]_奇 f[n] 的值会在更新后发生改变)

把新的 f [ 1 ] 偶 f[1]_偶 f[1] f [ 1 ] 奇 f[1]_奇 f[1] 的值带入,得到 f [ 2 ] 偶 = f [ 1 ] 奇 + 8 ∗ f [ 1 ] 偶 = 1 + 8 ∗ 9 = 73 f[2]_偶 = f[1]_奇 + 8 * f[1]_偶=1+8*9=73 f[2]=f[1]+8f[1]=1+89=73

即为样例答案 73。

同理, f [ 2 ] 奇 = f [ 1 ] 偶 + 8 ∗ f [ 1 ] 奇 = 9 + 8 ∗ 1 = 17 f[2]_奇 = f[1]_偶 + 8 * f[1]_奇=9+8*1=17 f[2]=f[1]+8f[1]=9+81=17

上面这个 f [ 1 ] 偶 f[1]_偶 f[1] f [ 1 ] 奇 f[1]_奇 f[1] 为什么要更新的的原因,是本题的难点,也是本题的解题关键。现在不理解也没关系,继续往下阅读,再分析一个案例,也许你就理解了。


然后以 N = 3 N=3 N=3,即 三位数 为例,也是类似的过程。

对于 f [ 3 ] 偶 f[3]_偶 f[3],可以分两种情况:

  • 百位为 3,则 十位和个位总体 必须为 奇数个 3,数量为 f [ 2 ] 奇 f[2]_奇 f[2]
  • 百位不为 3,则 十位和个位总体 必须为 偶数个 3,数量为 f [ 2 ] 偶 f[2]_偶 f[2]

所以 f [ 3 ] 偶 = f [ 2 ] 奇 + 8 ∗ f [ 2 ] 偶 f[3]_偶 = f[2]_奇 + 8 * f[2]_偶 f[3]=f[2]+8f[2]

同理, f [ 3 ] 奇 = f [ 2 ] 偶 + 8 ∗ f [ 2 ] 奇 f[3]_奇 = f[2]_偶 + 8 * f[2]_奇 f[3]=f[2]+8f[2]

同样,由于在计算 f [ 2 ] 奇 f[2]_奇 f[2] f [ 2 ] 偶 f[2]_偶 f[2] 时,十位不能为0;而引入百位后,十位可以为 0,所以如果要输出的是三位数的结果,则在计算 f [ 2 ] 奇 f[2]_奇 f[2] f [ 2 ] 偶 f[2]_偶 f[2] 时,也需要考虑 0


现在我们 重新计算 求解 f [ 3 ] 偶 f[3]_偶 f[3] f [ 3 ] 奇 f[3]_奇 f[3] 情况下的 f [ 2 ] 偶 f[2]_偶 f[2] f [ 2 ] 奇 f[2]_奇 f[2]

我们在上一步中计算的 f [ 2 ] 偶 = f [ 1 ] 奇 + 8 ∗ f [ 1 ] 偶 = 1 + 8 ∗ 9 = 73 f[2]_偶 = f[1]_奇 + 8 * f[1]_偶=1+8*9=73 f[2]=f[1]+8f[1]=1+89=73

其中 8 这个系数,是十位不为 3 ,取 1~2,4~9 得到的(当时十位不能为 0)。但是现在,由于十位可以为0 ,所以十位可以取 0~2,4~9 共 9 个数字,所以上面式子中的系数应该为 9,而不是 8。

所以新的 f [ 2 ] 偶 = f [ 1 ] 奇 + 9 ∗ f [ 1 ] 偶 = 1 + 9 ∗ 9 = 82 f[2]_偶 = f[1]_奇 + 9 * f[1]_偶=1+9*9=82 f[2]=f[1]+9f[1]=1+99=82

同理,新的 f [ 2 ] 奇 = f [ 1 ] 偶 + 9 ∗ f [ 1 ] 奇 = 9 + 9 ∗ 1 = 18 f[2]_奇 = f[1]_偶 + 9 * f[1]_奇=9+9*1=18 f[2]=f[1]+9f[1]=9+91=18

在得到了新的 f [ 2 ] 偶 f[2]_偶 f[2] f [ 2 ] 奇 f[2]_奇 f[2] 后,再带入 f [ 3 ] 偶 = f [ 2 ] 奇 + 8 ∗ f [ 2 ] 偶 f[3]_偶 = f[2]_奇 + 8 * f[2]_偶 f[3]=f[2]+8f[2],就能得到正确的 f [ 3 ] 偶 f[3]_偶 f[3]

🍉 PS: f [ 3 ] 偶 = f [ 2 ] 奇 + 8 ∗ f [ 2 ] 偶 f[3]_偶 = f[2]_奇 + 8 * f[2]_偶 f[3]=f[2]+8f[2],这里的系数 8 并不会变成 9,因为此时百位是最高位,不能为 0。

但是同理,当 N = 4 N=4 N=4 时,由于有千位的存在,百位就可以为 0 ,那么计算 f [ 3 ] 偶 f[3]_偶 f[3] 时,其数值就应该更新为 f [ 3 ] 偶 = f [ 2 ] 奇 + 9 ∗ f [ 2 ] 偶 f[3]_偶 = f[2]_奇 + 9 * f[2]_偶 f[3]=f[2]+9f[2]

上面推导过程中, f [ 2 ] 偶 f[2]_偶 f[2] f [ 2 ] 奇 f[2]_奇 f[2] 为什么要更新,并且 「公式系数从 8 改为 9」的原因,以及计算 f [ 3 ] 偶 f[3]_偶 f[3] f [ 3 ] 奇 f[3]_奇 f[3] 时,「公式系数仍为 8 」的原因,是本题的难点,也是本题的解题关键。⭐️


根据上面的推导,我们可以得到最终 n 位数的结果

  • f [ n ] 偶 = f [ n − 1 ] 奇 + 8 ∗ f [ n − 1 ] 偶 f[n]_偶 = f[n-1]_奇 + 8 * f[n-1]_偶 f[n]=f[n1]+8f[n1]

  • f [ n ] 奇 = f [ n − 1 ] 偶 + 8 ∗ f [ n − 1 ] 奇 f[n]_奇 = f[n-1]_偶 + 8 * f[n-1]_奇 f[n]=f[n1]+8f[n1]

而在计算 f [ n − 1 ] 奇 f[n-1]_奇 f[n1] f [ n − 1 ] 偶 f[n-1]_偶 f[n1] 时,由于此时最高位可以为 0,上面递推式中表示 1~2,4~9的系数「8」就变成了0~2,4~9的系数「9」,递推公式为:

  • f [ n − 1 ] 偶 = f [ n − 1 ] 奇 + 9 ∗ f [ n − 1 ] 偶 f[n-1]_偶 = f[n-1]_奇 + 9 * f[n-1]_偶 f[n1]=f[n1]+9f[n1]

  • f [ n − 1 ] 奇 = f [ n − 1 ] 偶 + 9 ∗ f [ n − 1 ] 奇 f[n-1]_奇 = f[n-1]_偶 + 9 * f[n-1]_奇 f[n1]=f[n1]+9f[n1]

所以在书写代码时,也需要分为两个表达式来写。✅

🍉 PS1:在实际编程中,我们可以用 f [ N ] [ 0 ] f[N][0] f[N][0] 来表示 f [ N ] 偶 f[N]_偶 f[N] ,用 f [ N ] [ 1 ] f[N][1] f[N][1] 来表示 f [ N ] 奇 f[N]_奇 f[N]

🍉 PS2:这种递推问题的答案可能很大,甚至超出 long long 的范围,所以不要忘记题干中的取模要求。


🧑🏻‍💻 C++ 代码

#include<bits/stdc++.h>

using namespace std;

const int N = 1e3 + 10;
const int K = 12345;
int n;
int f[N][2];  //f[n][0]表示 n位数 中包含偶数个3的情况

int main() {
    ios::sync_with_stdio(false);  //cin读入优化
    cin.tie(0);

    cin >> n;
    if (n == 1) {
        f[1][0] = 8;  //1~2,4~9 共 8 个
        f[1][1] = 1;  //3,共1个
        cout << f[1][0] << endl;
    } else {
        f[1][0] = 9;  //更高位上有数字,需要考虑0
        f[1][1] = 1;
      
        //递推2~n-1位数
        for (int i = 2; i <= n - 1; ++i) {
            //K = 12345
            f[i][0] = ((f[i - 1][1] % K) + (9 * (f[i-1][0] % K)) % K) % K;
            f[i][1] = ((f[i - 1][0] % K) + (9 * (f[i-1][1] % K)) % K) % K;
        }

        //单独计算n位数
        f[n][0] = ((f[n - 1][1] % K) + (8 * (f[n-1][0] % K)) % K) % K;
        cout << f[n][0] << endl;
    }

    return 0;
}

image-20221215141136381


😑 吐槽时间

博主本人在阅读其他一些题解时,发现有的题解在分析时,认为 f [ 1 ] [ 0 ] = 8 f[1][0]=8 f[1][0]=8( 1~2,4~9,因为 0 不算一位数),但是实际代码中,却出现 f [ 1 ] [ 0 ] = 9 f[1][0] = 9 f[1][0]=9 的情况,并且没有交代原因。这样的前后矛盾,让不少看题解的小伙伴们感到困惑。

博主还发现,有的题解就直接认为 f [ 1 ] [ 0 ] f[1][0] f[1][0] 就应该等于 9,把 0 也算成了一位数,这从 数学定义的角度 来看是错误的。❌ (有疑惑的小伙伴可以查阅以下问题:0 算不算一位数 ? 一位数和个位数有什么区别?)

从推导过程中,我们看到只有在 N > 1 N > 1 N>1 时,f[1][0] 才因为进制的规则,变成了 9。

说明写其他题解的作者可能没有仔细考虑这其中的关系,这也是博主本人撰写此篇题解的原因,希望本题解能真正解答一些小伙伴们的困难。


我也希望阅读此篇题解后,理解了本题的小伙伴,在未来自己写其他题目的题解时,多一份耐心与细致,不要让更多灌水、没有太多思考的题解,污染了这片土壤,浪费其他小伙伴搜索与阅读的时间。☘️


如果小伙伴们觉得博主写的不错,可以给文章点个赞,让优质的文章有更大的概率出现在搜索榜单的前面,为未来的小伙伴们节约更多搜索、阅读的成本。

同时你的支持也是我不断创作的动力。😃

有想要看更多题解报告的小伙伴,也可以关注我的专栏「信息奥赛题解」。

我们下期再见。👋


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/91032.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis】数据类型操作一 (key/String/List)

文章目录0、Redis键(key)1、Redis字符串(String)2、Redis列表(List)实操0、Redis键(key)1、Redis字符串(String)2、Redis列表(List)0、Redis键(key) 切换数据库 select dbid select 8 清空数据库 flushdb &#xff08;清空当前库&#xff09; flushall &#xff08;通杀全部库…

python机器学习与深度学习在气象中如何应用??如台风预报数据智能订正、预测风电场的风功率、预测浅水方程模式

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;在数据处理、科学计算、数学建模、数据挖掘和数据可视化方面具备优异的性能&#xff0c;这些优势使得Python在气象、海洋、地理、气候、水文和生态等地学领域的科研和工程项目中得到广泛应用。可以…

年终洞察:日本正兴起一波“反向海淘”

这两天&#xff0c;正在日本备婚的李杨&#xff08;化名&#xff09;收到了“漂洋过海”从Starday跨境电商服务平台买来的喜庆装饰品&#xff0c;“这些烘托传统中国婚礼的独特装饰品在日本是很难买到的”从她打开Starday跨境电商服务平台&#xff0c;选择心仪的装饰品并并下单…

[附源码]Python计算机毕业设计高校线上教学系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

mysql查询基础

查询执行图 查询顺序 explain 参数说明 Id: MySQL QueryOptimizer 选定的执行计划中查询的序列号。表示查询中执行select 子句或操作表的顺序,id 值越大优先级越高,越先被执行。id 相同,执行顺序由上至下 Select_type: 一共有9中类型,只介绍常用的4种: SIMPLE: 简单的 select 查…

前端——给图形绘制阴影

给图形绘制阴影 在HTML5中&#xff0c;使用canvas元素可以给图形添加阴影效果。添加阴影效果时&#xff0c;只需利用图形上下文对象的几个关于阴影绘制的属性就可以了&#xff0c;这几个属性如下。 shadowOffsetX——阴影的横向位移量。 shadowOffsetY——阴影的纵向位移量。…

提面优秀资格上岸浙大MBA经验分享

三百多天的备考&#xff0c;终于等来了一个好的结果。曾经的我也一直在犹豫到底要不要放弃对于浙大的执念&#xff0c;虽然说我的工作是还行&#xff0c;但是我的第一学历只是一个不入流的二本院校&#xff0c;当时咨询的老师说是对于浙大提面来说&#xff0c;我肯定是要吃学历…

MobSDK引进相关问题

1、进入全球领先的数据智能科技平台-MobTech袤博mob官网 首先注册帐号、核验身份、选择开发者平台 2、创建项目的appkey和对应的appSecret 进入开发者模式后&#xff0c;对应以下几个选项模块&#xff08;以短信验证模块为例&#xff09;&#xff0c;点击开始使用 跳转到个人…

[附源码]Nodejs计算机毕业设计基于的宠物领养管理系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

怎么将语音转为文字?不如试试这几个语音转文字软件app

随着时代的发展&#xff0c;现在许多小伙伴会将重要却来不及整理的内容&#xff0c;用录音或是语音的方式记录下来&#xff0c;之后再进行整理。但是在整理的时候&#xff0c;有些人可能会因为需要多听几遍音频才能完成工作而感到痛苦&#xff0c;毕竟这样做&#xff0c;花费的…

Elasticsearch版本升级实践、注意事项

版本关系 从官方文档看可以发现两个大版本升级需要关注到具体的版本&#xff0c;比如想从 5.x 版本升级到 7.x 版本&#xff0c;就必须先升级到 6.8 版本&#xff0c;再从 6.8 升级到 7.x 版本。 检查是否可以升级 1. 版本号确认 2. 通过API检查是否存在过期的用法 # ES 6.xG…

【夯实Kafka知识体系及基本功】「实践操作篇」单机部署实践手册(2.8.0)

来一段舞蹈 前提回顾 下载kafka wget https://archive.apache.org/dist/kafka/0.8.0/kafka_2.8.0-0.8.0.tar.gz或者 curl -O https://archive.apache.org/dist/kafka/0.8.0/kafka_2.8.0-0.8.0.tar.gz解压缩 tar -vxf kafka_2.8.0-0.8.0.tar.gz修改配置 修改conf/server.pro…

IAA品类洞察:扫描品类加快变现,如何抓住增长机遇?

易观分析&#xff1a;工具产品是IAA行业中的经典品类&#xff0c;开发门槛较低、变现模式成熟。从近期的商业化表现来看&#xff0c;我们关注到其中的扫描品类呈现高速增长之势&#xff0c;正释放出更多的发展潜力&#xff1a; ①行业方面&#xff1a;扫描品类的用户规模已超2千…

chatGPT实战之「基于你的数据库,为你智能生成SQL」

chatGPT为你生成SQL的落地效果演示 这几天很很多粉丝进行了深度交流&#xff0c;发现大家对于SQL学习或者编写都遇到过困难&#xff0c;因此勇哥突发奇想是否可以借助chatGPT来帮一下大家呢&#xff1f;于是就开启了chatGPT的落地之旅。从官网了解到chatGPT支持49种场景的&…

【webpack】使用webpack api打包一个最简单的js资源

简单了解一下webpack 本质上&#xff0c;webpack是一个用于现代javascript应用程序的静态模块打包工具。当webpack处理应用程序时&#xff0c;它会在内部从一个或多个入口点构建一个依赖图&#xff0c;然后将项目中所需要的每一个模块组合成一个或多个bundles&#xff0c;它们均…

前端_Vue_5.列表渲染

文章目录一、列表渲染1.1. v-for1.2. v-for 与对象1.3. 在 v-for 里使用范围值1.4. \<template\> 上的 v-for1.5. v-for 与 v-if1.6. 通过key管理状态1.7. 组件上使用 v-for1.8. 数组变化侦测1.8.1. 变更方法1.8.2. 替换一个数组1.9. 展示过滤或排序后的结果一、列表渲染…

最近的取款机

一 问题描述 在每台有故障的自动取款机上都贴着一个标签&#xff0c;提示客户去最近的取款机上取款。已知 n 台自动取款机的二维位置列表&#xff0c;为每台自动取款机都找到一个距离最近的自动取款机。 二 输入和输出 1 输入 第 1 行包含测试用例数 T&#xff08;T≤15&am…

Flinkcdc同步mysql到StarRocks(删除)

Flink 使用mysql cdc实时监听mysql并且同步到StarRocks&#xff08;SR&#xff09; 问题&#xff1a;我们在使用过程中请注意cdc版本和flink的版本&#xff0c;目前flink 1.15.2还没有很好地cdc兼容版本有能力的可以自己编译&#xff0c;参见目前版本兼容&#xff1b; SR官方推…

分布式光伏发电计及气象因子及出力预测方法研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【WebGL-iTwin.js】理论篇(一):webgl中三维模型表示方式-多边形网格

一、三维模型表示方式 在计算机图形学中&#xff0c;三维模型一般是指空间中物理实体对象的数学表示。具体说来&#xff0c;三维模型是由其形状和颜色外观的描述构成。通常&#xff0c;三维对象的表示方法可以分为面表示和体表示两种类型。 面表示&#xff1a; 也就是表示三维…