题解:P11655 「FAOI-R5」Lovely 139

news/2025/2/2 23:49:09/文章来源:https://www.cnblogs.com/Domi2011/p/18697256

P11655 题解

题目传送门

题目描述

给定两个非负整数 n 和 m,计算所有包含 n 个 0 和 m 个 1 的 01 字符串的极长颜色段数之和。

极长颜色段的定义是连续相同字符的最大子串。例如:

0011 的极长颜色段数为 2(两个 0 和两个 1)

0101 的极长颜色段数为 4(每个字符交替)

最终结果对 1e9+7 取模。 //补药忘记取模qwq

解题思路

通过观察不难发现极长颜色段的数量等于相邻字符不同的位置数目加一例如,字符串 0011 中相邻不同的位置数目为1,段数为1+1=2

因此,问题转化为计算所有字符串中相邻字符不同的位置数目之和,再加字符串总数

然后再推一下公式

1.字符串总数:n 个 0 和 m 个 1 排列的总数为组合数 C(n+m,n)

2.相邻不同的位置数目之和:假设某个位置是相邻不同的,这样的位置共有 (n+m-1) 种可能。又因每个位置的贡献为 2 * C(n+m-2,n-1)。所以总贡献为2 * (n+m-1) * C(n+m-2,n-1)

最终公式为:

g(n,m) = C(n+m,n)+2 * (n+m-1) * C(n+m-2,n-1)

特殊情况

当 n=0 且 m=0 时,答案为 1(空字符串)。

当 n=0 或 m=0 时,字符串全为同一字符,段数为 1。

代码 + 注释

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
const int MAXN = 2e6 + 10;
int f[MAXN],dp[MAXN]; //f存储阶乘,dp存储逆元
//快速幂计算逆元
int k(int x,int y)
{int r = 1;while(y){if (y & 1) r = r * x % mod;x = x * x % mod;y >>= 1;}return r;
}
//计算组合数 C(a, b),利用公式 C(a,b) = a!/(b!(a-b)!)。
int c(int a,int b)
{if(a < 0 || b < 0 || a < b) return 0;return f[a] * dp[b] % mod * dp[a - b] % mod;
}
//特判:处理 n 或 m 为 0 的情况。
//公式实现:根据推导公式计算总和。
int g(int n,int m)
{if(n == 0 && m == 0) return 1;if(n == 0) return 1;if(m == 0) return 1;int tot = (n + m - 1) % mod;tot = tot * 2 % mod;tot = tot * c(n + m - 2,n - 1) % mod;int ans = (c(n + m,n) + tot) % mod;return ans;
}
signed main()
{//预处理阶乘和逆元数组f[0] = 1;for(int i = 1;i < MAXN;i++){f[i] = f[i - 1] * i % mod;}dp[MAXN - 1] = k(f[MAXN - 1],mod - 2);for(int i = MAXN - 2;i >= 0;i--){dp[i] = dp[i + 1] * (i + 1) % mod;}//阶乘数组 f:f[i] = i! % mod。//逆元数组 dp:dp[i] = (i!)^{-1} % mod,通过费马小定理计算。int T;cin >> T;while(T--){int n,m;cin >> n >> m;cout << g(n,m) << "\n";//输出就ok了}return 0;
}

dp数组的作用详解

1.dp数组的定义

dp数组用于存储逆阶乘的模逆元。具体来说:

dp[i] 表示 i! 在模 mod 意义下的逆元,即:dp[i] = (i!)^{-1} % mod

例如,当i = 3时,dp[3]表示3!的逆元,即6^{-1} mod 1e9+7。

2.为什么需要dp数组

组合数的计算需要除法,直接计算阶乘会导致数值过大,且模运算中除法不适用。

逆元的作用:
在模运算中,除以一个数等价于乘以它的逆元。

因此,dp 数组将除法转换为乘法,使得组合数的计算可行

3.dp数组的预处理过程

步骤 1:计算最大阶乘的逆元:

dp[MAXN - 1] = k(f[MAXN - 1], mod - 2);

利用费马小定理,当 mod 为质数时:

a^(-1) ≡ a^(mod-2) % mod;

这里 f[MAXN - 1] 是 (MAXN-1)!,通过快速幂计算其逆元。

步骤 2:递推计算所有逆阶乘:

for(int i = MAXN - 2;i >= 0;i--)
{dp[i] = dp[i + 1] * (i + 1) % mod;
}

4.dp数组在组合数计算中的应用

在函数c(a,b)中:

f[a] * dp[b] % mod * dp[a - b] % mod;

等价于组合数公式

通过 dp 数组将除法转换为乘法:

1 / b! = dp[b],1 / (a-b)! = dp(a-b);

无注释代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
const int MAXN = 2e6 + 10;
int f[MAXN],dp[MAXN];
int k(int x,int y)
{int r = 1;while(y){if (y & 1) r = r * x % mod;x = x * x % mod;y >>= 1;}return r;
}
int c(int a,int b)
{if(a < 0 || b < 0 || a < b) return 0;return f[a] * dp[b] % mod * dp[a - b] % mod;
}
int g(int n,int m)
{if(n == 0 && m == 0) return 1;if(n == 0) return 1;if(m == 0) return 1;int tot = (n + m - 1) % mod;tot = tot * 2 % mod;tot = tot * c(n + m - 2,n - 1) % mod;int ans = (c(n + m,n) + tot) % mod;return ans;
}
signed main()
{f[0] = 1;for(int i = 1;i < MAXN;i++){f[i] = f[i - 1] * i % mod;}dp[MAXN - 1] = k(f[MAXN - 1],mod - 2);for(int i = MAXN - 2;i >= 0;i--){dp[i] = dp[i + 1] * (i + 1) % mod;}int T;cin >> T;while(T--){int n,m;cin >> n >> m;cout << g(n,m) << "\n";}return 0;
}

完事

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【模拟电子技术】19-差分放大电路的构成

【模拟电子技术】19-差分放大电路的构成 我们知道在直接耦合放大电路中零点漂移是一个很困扰的问题(可以理解为静态工作点稳定问题),我们通过增加电阻Re来抑制温漂,前面我们也提到过有一种电路可以在直流的时候doubleRe,而交流的时候使得Re消失我们想要抑制这种现象,想到…

球钟问题

球钟问题,对栈和队列的实际应用球钟问题 1. 问题背景 ​ 球钟是一个利用球的移动来记录时间的简单装置。它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器和小时指示器。 举例:若分钟指示器中有2个球,五分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32…

本地部署deepseek

前言 如果你电脑配置不错,且期望不受网络限制也可以流畅使用deepseek,那就本地部署deepseek试试吧。下载并安装Ollama Ollama是一个开源的 LLM(大型语言模型)服务工具(就是大模型运行工具),用于简化在本地运行大语言模型,降低使用大语言模型的门槛,使得大模型的开发者…

【邮件安全】近期常见的钓鱼邮件(202411期)

本期主要分享自2024年11月至今几种典型的钓鱼邮件样本。希望通过这种分享,可以帮助广大用户提高警惕性,增强识别与防范钓鱼邮件的能力。 邮箱账户异常类 以下图为例,该钓鱼邮件伪造用户账户出现异常登录情况,引导用户点击“认证账户”按钮进入钓鱼页面。 下图是一封伪造用户…

AI医院:大语言模型在多智能体医疗交互模拟器中的表现如何?

近年来,人工智能(AI)技术,尤其是大语言模型(LLMs),在医学领域取得了显著进展。这些模型在静态医疗问答任务中表现优异,甚至在某些情况下能够媲美人类专家。然而,医学诊断并非单一静态的任务,而是一个动态、复杂的过程,涉及多轮互动和信息收集。 为了更全面地评估LLM…

万字综述|一文掌握大语言模型在生物信息学中的应用

随着大语言模型(LLMs)技术的飞速发展,其在自然语言处理(NLP)领域的成功应用逐渐扩展到了生物信息学领域。生物信息学作为一个跨学科的领域,涉及基因组学、蛋白质组学、药物发现等多个方向,LLMs的引入为这些领域带来了新的研究工具和方法。 2025年1月,佐治亚大学Tianmin…

自主做前端页面小工程07

通过使用elementui和js部分代码实现 其重点在于导航栏与弹窗和数据的回显与数据只可预览,基本完成 这是补发昨天学习记录

自主做前端小工程08

今天学习记录,完成部门经理页面,主要是分vue中的变量,创建了更多对话框页面和表单

【邮件安全】近期常见的钓鱼邮件(202412期)

# 钓鱼邮件样本 本期主要分享自2024年12月至今几种典型的钓鱼邮件样本。年关将至,大家要擦亮眼睛,谨防受骗! 带附件类钓鱼上图是一封带有html附件的钓鱼邮件,html附件中包含钓鱼页面。一旦用户打开html文件,可能会非法收集用户个人信息或引导用户输入账号密码等敏感信息。…

CTF-web过年加更

一、菜狗杯的无一幸免看代码可以发现$arr[]=1(在数组中追加一个数且赋值为1,永久为真),想要饶过它就需要让数组溢出(最大int数) int范围为32位:2的31次方-1=2147483647;64位:2的63次方-1=9,223,372,036,854,775,807 在顶部传入参数0=(以上2个看情况选)即可拿到flag二…

python 项目工程化开发

虚拟环境工具 安装poetry pip install -U peotry上述方式不行时 (Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python加入环境变量初始化项目 安装cookiecutter pip install -U cookiecutter初始化项目 cd workspace cookiecutter …

Java-GUI编程-五子棋游戏

java-gui编程-五子棋小游戏 文件目录如下: 棋盘背景图如下: 运行效果如下: FiveChess类代码: package com.gui.fivechess;public class FiveChess { //主类,运行该类即可启动游戏 public static void main(String[] args) { FiveChessFrame ff = new FiveChe…