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

1313:【例3.5】位数问题


时间限制: 1000 ms         内存限制: 65536 KB
提交数:39515    通过数: 21452

【题目描述】

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

【输入】

读入一个数N(N≤1000)𝑁(𝑁≤1000)。

【输出】

输出有多少个数中有偶数个数字33。

【输入样例】

2

【输出样例】

73

【原题链接】

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)icon-default.png?t=N7T8https://ybt.ssoier.cn/problem_show.php?pid=1313

分析

① 当N=1时,所有的一个数为0、1、2、3、4、5、6、7、8、9,其中,含偶数个3的数字为0、1、2、4、5、6、7、8、9,共9个。
② 当N=2时,分为两种情况:

如果第二个数字是3,那么第一个数字必也是3(两个3)-------(一种情况);
如果第二个数字不是3(九种情况),第一个数字也不是3且不能为0(八种情况),共8 x 9 = 72种可能。

如何得到n位数中包含偶数个3的方案数呢?

  1. 假设一个n位数最后一位数字是3,那么只有满足其前n - 1位包含奇数个3,才可以使n位包含偶数个3,即f[n - 1][1]。
  2. 假设一个n位数最后一位数字不是3,可能取0、1、2、4、5、6、7、8、9(最后一位有9种情况),那么只有满足其前n - 1位包含偶数个3,才可以使n位包含偶数个3,即f[n - 1][0] * 9。

综上,当N=2时,一共有73个数字包含偶数个3。

初始化一位数情况下的方案数:

  • f[n][0]表示包含偶数个3的n位数的个数。
  • f[n][1]表示包含奇数个3的n位数的个数。

int num = 9;

 if (i == n) num = 8;

  • 根据位数确定非首位元素可以为 0 的可能性数:
    • 如果 i 不是 n,则有 9 种可能性(0 到 9)。
    • 如果 i 是 n,则首位不能为 0,有 8 种可能性(1 到 9)。

 f[i][0] = (f[i - 1][1] + f[i - 1][0] * num) % 12345;

  • 计算 i 位数中包含偶数个3的方案数:
    • 从 i-1 位数中包含奇数个3的方案数转移过来,加上 i-1 位数中包含偶数个3的方案数乘以 num。
    • 取模操作,避免数值溢出,模数为 12345。

f[i][1] = (f[i - 1][0] + f[i - 1][1] * num) % 12345;

  • 计算 i 位数中包含奇数个3的方案数:
    • 从 i-1 位数中包含偶数个3的方案数转移过来,加上 i-1 位数中包含奇数个3的方案数乘以 num。
    • 同样进行模运算。

通过动态规划的思想计算了包含特定数量的数字3的 n 位数的方案数,使用了数组 f 来保存中间状态,从而避免了重复计算,提高了效率。

#include <iostream>  //包含输入输出流头文件和使用标准命名空间。

using namespace std;

const int N = 1010;  //常量定义 N,用于定义数组 f 的大小。

int f[N][2];  //二维数组 f,用来存储状态信息,f[i][0] 表示 i 位数中包含偶数个3的方案数,f[i][1] 表示 i 位数中包含奇数个3的方案数。

int main()  //主函数开始。
{
    int n;
    cin >> n;  // 输入变量 n,表示要计算包含 n 位数的方案数。

    //f[1][0] 初始化为 9,即一位数中包含偶数个3的方案数(0, 1, 2, 4, 5, 6, 7, 8, 9)。
    //f[1][1] 初始化为 1,即一位数中包含奇数个3的方案数(3)。
    f[1][0] = 9;
    f[1][1] = 1;

    //递推
    for (int i = 2; i <= n; i++)  //开始递推计算从 2 到 n 位数的方案数。
    {
        int num = 9;
     
        if (i == n) num = 8;

        f[i][0] = (f[i - 1][1] + f[i - 1][0] * num) % 12345;
       
        f[i][1] = (f[i - 1][0] + f[i - 1][1] * num) % 12345;
    }

    cout << f[n][0] << endl;  //输出 n 位数中包含偶数个3的方案数。
    return 0;  //返回主函数结束。
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值