%3 题解(组合计数+隔板法)

Description

给定 n , m n,m n,m,求满足以下条件的整数序列 A = ( a 1 , a 2 , … , a N ) A = (a_1, a_2, \ldots, a_N) A=(a1,a2,,aN) 的个数模 998244353 998244353 998244353 的值。

条件:

  • ∀ i ∈ [ 1 , n ) : a i ≢ a i + 1 ( m o d 3 ) ∧ a i ≤ a i + 1 \forall i \in [1,n):\ a_i \not\equiv a_{i+1} \pmod 3\ \wedge\ a_i \le a_{i+1} i[1,n): aiai+1(mod3)  aiai+1

  • a i ∈ [ 0 , m ] a_i \in [0,m] ai[0,m]

Analysis

首先这道题有一个很套路的 dp 做法:设 f i , j f_{i,j} fi,j 表示第 i i i 个数,上一个选的数取模 3 3 3 的余数为 j j j 的方案数。这样转移复杂度是 O ( n m ) O(nm) O(nm) 的。

考虑用组合数学的计算方法优化成线性复杂度。

发现相邻两项不同余 3 3 3 其实就相当于相邻两项的差不整除 3 3 3

则我们可以用差分数组来改变一下题目的原有条件。

定义:
∀ i ∈ [ 2 , n ] : d i = a i − a i − 1 d 1 = a 1 \forall i \in [2,n]:d_i = a_i - a_{i-1} \\ d_1 = a_1 \\ i[2,n]:di=aiai1d1=a1
则题目要求 ∀ i ∈ [ 2 , n ] : d i ≢ 0 ( m o d 3 ) \forall i \in [2,n]: d_i \not\equiv 0 \pmod 3 i[2,n]:di0(mod3)。也就是在满足条件的 A A A 中, d i d_i di 可以被表示为 3 k + 1 3k+1 3k+1 3 k + 2 3k+2 3k+2 的形式。

看到这里脑中就应该浮现出隔板法的模型了。题目就又可以转化为:
假设  ∃ a n + 1 = m ⇒ ∑ i = 1 n + 1 d i = m ⇒ 求不定方程  x 1 + x 2 + ⋯ + x n + 1 = m ( x i ∈ N ) 的解的组数 假设\ \exist a_{n+1}=m \\ \Rightarrow \sum\limits_{i=1}^{n+1} d_i=m \\ \Rightarrow 求不定方程\ x_1 + x_2 + \cdots + x_{n+1} = m\ (x_i \in \mathbb{N})\ 的解的组数 假设 an+1=mi=1n+1di=m求不定方程 x1+x2++xn+1=m (xiN) 的解的组数
根据隔板法,若不考虑 d i d_i di 的限制,我们可能会立刻想到答案为 ( m + 1 n ) \dbinom{m+1}{n} (nm+1)

解释也很简单:在我们要把数字 m m m 分成 n + 1 n+1 n+1 份,就相当于在值域 [ 0 , m ] [0,m] [0,m] m + 1 m+1 m+1 个数里插 n n n 个隔板。

但这是不对的。

原因是这道题和常规的隔板不大一样,常规隔板是 n n n 个元素往 m m m 个空里放,两个元素不能放到同一个空里。这样答案是 ( m n ) \dbinom{m}{n} (nm),但这道题两个物品可以放在同一个空里面(因为 x x x 可以为 0 0 0)。

我们考虑如何转化,有一个很妙的思路:考虑将等式左边的所有 x x x 都加上 1 1 1,这样就能保证所有的 x ≥ 1 x \ge 1 x1。此时原方程变为: x 1 + x 2 + ⋯ + x n + 1 = m + n + 1 x_1 + x_2 + \cdots + x_{n+1} = m+n+1 x1+x2++xn+1=m+n+1,此时再用正常的隔板法就能求得正确的答案了: ( m + n n ) \dbinom{m+n}{n} (nm+n)。(上面不是 m + n + 1 m+n+1 m+n+1 是因为此时 x x x 一定不为 0 0 0,所以答案的值域实际为 [ 1 , m + n ] [1,m+n] [1,m+n]

还有一种更巧妙的解释方式。考虑把隔板也看成是一个物品,那么我们此时就有 m + n m+n m+n 个物品,我们只要选出 n n n 个隔板所在的位置,就能确定剩下物品的位置。所以选定隔板的方案数就是总的方案数: ( m + n n ) \dbinom{m+n}{n} (nm+n),答案一样。但第一个方法是一个通法,适用范围更广。

然后考虑加上不同余 3 3 3 的限制。承接上文,所有的 d i ( 1 < i < n + 1 ) d_i(1 < i < n+1) di(1<i<n+1) 都可以表示为 3 k + 1 3k+1 3k+1 3 k + 2 3k+2 3k+2 的形式。

发现隔板法其实可以转化为一个“分数字”的过程。

所以我们可以枚举有 x x x d i d_i di 3 k + 1 3k+1 3k+1,那么就有 n + 1 − x n+1-x n+1x 3 k + 2 3k+2 3k+2(因为一共 n + 1 n+1 n+1 个数)。

因为所有的 d i d_i di 都有 3 k 3k 3k 这个部分,所以我们先放多出来的 1 1 1 2 2 2。这样,摆在我们面前的问题就是:所有的 d i d_i di 初始都是 0 0 0,我们要把 x x x 1 1 1 n + 1 − x n+1-x n+1x 2 2 2 分给所有的 d i d_i di。要注意的是分完之后只有 d 1 d_1 d1 d n + 1 d_{n+1} dn+1 可以是 0 0 0,剩下的必须是 1 1 1 2 2 2

那么,单独放 1 1 1 2 2 2 的方案数显然就是 ( n + 1 x ) \dbinom{n+1}{x} (xn+1)。(确定了放 1 1 1 的个数后 2 2 2 的直接就放上去就可以)

因为现在我们不确定 d 1 d_1 d1 d n + 1 d_{n+1} dn+1,所以我们可以先枚举 d 1 ∈ [ 0 , 2 ] d_1 \in [0,2] d1[0,2]。( d n + 1 d_{n+1} dn+1 先不急,后面有妙用)

分完之后,我们要分的数还剩下 m − d 1 − x − 2 ( n + 1 − x ) m - d_1 - x - 2(n+1-x) md1x2(n+1x)(如果剩下的数小于 0 0 0 无解),这些数要变成若干个 3 k 3k 3k 分给 n + 1 n+1 n+1 个数,其实就是变成若干个 3 3 3 分给每个数。(因为我们不关注具体的分数过程,只关心方案数)

我们希望 m − d 1 − x − 2 ( n + 1 − x ) m - d_1 - x - 2(n+1-x) md1x2(n+1x) 一定是 3 3 3 的倍数,这样是符合我们上面的逻辑的。但一切事情都不会进行的那么顺利,假设它不是 3 3 3 的倍数,因为我们还没分 d n + 1 d_{n+1} dn+1,我们就可以利用处于“法外之地”的 d n + 1 d_{n+1} dn+1 使它变成 3 3 3 的倍数。即 d n + 1 d_{n+1} dn+1 的值一定是 [ m − d 1 − x − 2 ( n + 1 − x ) ] m o d 3 [m-d_1-x-2(n+1-x)] \bmod 3 [md1x2(n+1x)]mod3

现在,解决了余数的问题,我们要分的 3 3 3 的个数就是 p = ⌊ m − d 1 − x − 2 ( n + 1 − x ) 3 ⌋ p = \lfloor\dfrac{m-d_1-x-2(n+1-x)}{3}\rfloor p=3md1x2(n+1x) 了。

把这么多个 3 3 3 分给 n n n 个数,根据上面讲的隔板法,方案数即为: ( p + n n ) \dbinom{p+n}{n} (np+n)

最后的最后,把分 1 , 2 1,2 1,2 的方案数和分 3 3 3 的方案数乘起来即为答案: ( n + 1 x ) ( p + n n ) \dbinom{n+1}{x}\dbinom{p+n}{n} (xn+1)(np+n)

这道题相当于 NOIP T2 的难度,是一道数学推导的好题!关键在于转换差分数组和想到”分数字“这一重要操作。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e7 + 2e6; // C(n+p,n) 中n+p可能大于1e7,要开得大一点
const int mod = 998244353;
typedef long long ll;int fac[maxn], ifac[maxn]; // 阶乘、阶乘逆元(开int数组减小空间)ll Pow(ll x, ll y){ // 快速幂if(y == 0) return 1;if(y == 1) return x % mod;ll sq = Pow(x, y / 2);if(y & 1){return sq * sq % mod * x % mod;}return sq * sq % mod;
}int C(int n, int m){ // C(n,m): n个数里选m个的组合数// C(n,m) = n! / [m! * (n-m)!]return (n < m || m < 0)? 0 : (1LL * fac[n] * ifac[m] % mod * ifac[n - m] % mod);
}void pretreatment(){// 求普通阶乘fac[0] = 1;for(int i = 1; i < maxn; i ++) fac[i] = 1LL * fac[i - 1] * i % mod;// 递推求阶乘逆元ifac[maxn - 1] = Pow(fac[maxn - 1], mod - 2);for(int i = maxn - 2; i >= 0; i --) ifac[i] = 1LL * ifac[i + 1] * (i + 1) % mod;
}signed main()
{pretreatment();int n, m; cin >> n >> m;ll ans = 0;for(int x = 0; x <= n - 1; x ++){for(int d1 : {0, 1, 2}){int p = (m - d1 - x - 2*(n - 1 - x));if(p < 0) continue;p /= 3; // 细节:先除3有可能让一个负数变成0(例如-2/3=0,所以要先判断再除)ans += 1LL * C(n - 1, x) * C(p + n, n) % mod;ans %= mod;}}cout << ans << '\n';return 0;
}

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

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

相关文章

EF Core中实现值对象

目录 值对象优点 值对象的需求 值类型的实现 值类型GEO的实现 值类型MultilingualString的实现 案例&#xff1a;构建表达式树&#xff0c;简化值对象的比较 值对象优点 把有紧密关系的属性打包为一个类型把领域知识放到类的定义中 class shangjia {long id;string nam…

ETHEREAL:使用压缩Tsetlin机器实现能效高吞吐量推理

论文标题 英文标题&#xff1a;ETHEREAL: Energy-efficient and High-throughput Inference using Compressed Tsetlin Machine 中文标题&#xff1a;ETHEREAL&#xff1a;使用压缩Tsetlin机器实现能效高吞吐量推理 作者信息 Shengyu Duan, Newcastle University, Newcastle…

PyCharm 批量替换

选择替换的内容 1. 打开全局替换窗口 有两种方式可以打开全局替换窗口&#xff1a; 快捷键方式&#xff1a; 在 Windows 或 Linux 系统下&#xff0c;按下 Ctrl Shift R。在 Mac 系统下&#xff0c;按下 Command Shift R。菜单操作方式&#xff1a;点击菜单栏中的 Edit&…

mars3d接入到uniapp的时候ios上所有地图的瓦片都无法加载解决方案

用的是【Mars3d】官网的uniapp的仓库&#xff0c;安卓没有问题&#xff0c;但是ios的不行 相关链接 mars3d-uni-app: uni-app技术栈下的Mars3D项目模板 解决方案&#xff1a;感觉所有图片请求全被拦截了 uniapp的ios内核不允许跨域&#xff0c;需要先把瓦片下载后转base64&…

SpringBoot速成(十)更新用户信息P11-P12

1.代码展示&#xff1a; 1.RequestBody 是 Spring 框架中用于处理 HTTP 请求体的注解&#xff0c;通常用于控制器&#xff08;Controller&#xff09;层的方法参数中。当客户端发送一个包含 JSON 或 XML 数据的 HTTP 请求时&#xff0c;可以使用 RequestBody 将这些数据绑定到一…

3.3.3 VO-O语法- 语法算子(二)

循环遍历 由于VO语言是面向数据集的&#xff0c;其所有隐含的语义中都已经带有了遍历并计算的数据逻辑。因此&#xff0c;VO语言只提供了一种支持循环语法的算子--Loop算子。 Loop算子 Loop算子是一个容器算子&#xff0c;其可以实现对其内部子流程的循环迭代运行。但Loop算…

java后端开发day13--面向对象综合练习

&#xff08;以下内容全部来自上述课程&#xff09; 注意&#xff1a;先有javabean&#xff0c;才能创建对象。 1.文字版格斗游戏 格斗游戏&#xff0c;每个游戏角色的姓名&#xff0c;血量&#xff0c;都不相同&#xff0c;在选定人物的时候&#xff08;new对象的时候&#…

RocketMQ和Kafka如何实现顺序写入和顺序消费?

0 前言 先说明kafka&#xff0c;顺序写入和消费是Kafka的重要特性&#xff0c;但需要正确的配置和使用方式才能保证。本文需要解释清楚Kafka如何通过分区来实现顺序性&#xff0c;以及生产者和消费者应该如何配合。   首先&#xff0c;顺序写入。Kafka的消息是按分区追加写入…

DeepSeek系统崩溃 | 极验服务如何为爆火应用筑起安全防线?

引言 极验服务让您的产品站在风口之时&#xff0c;不必担心爆红是灾难的开始&#xff0c;而是期待其成为驱动持续创新的全新起点。 01现象级狂欢背后&#xff0c;你的业务安全防线抗得住吗&#xff1f; “近期DeepSeek线上服务受到大规模恶意攻击&#xff0c;注册可能繁忙&am…

【故障处理】- RMAN-06593: platform name ‘Linux x86 64-bitElapsed: 00:00:00.00‘

【故障处理】- RMAN-06593: platform name Linux x86 64-bitElapsed: 00:00:00.00 一、概述二、报错原因三、解决方法 一、概述 使用xtts迁移&#xff0c;在目标端进行恢复时&#xff0c;遇到RMAN-06593: platform name Linux x86 64-bitElapsed: 00:00:00.00’报错。 二、报错…

日志结构化处理:PO对象toString日志转JSON工具

日志结构化处理&#xff1a;PO对象toString日志转JSON工具 1. 解决的问题2. 下载地址 在Java项目中&#xff0c;PO&#xff08;Plain Old Java Object&#xff09;对象遍布各个角落&#xff0c;且常常伴随着大量的日志记录需求。传统的做法是通过toString方法直接打印这些对象&…

【云安全】云原生- K8S API Server 未授权访问

API Server 是 Kubernetes 集群的核心管理接口&#xff0c;所有资源请求和操作都通过 kube-apiserver 提供的 API 进行处理。默认情况下&#xff0c;API Server 会监听两个端口&#xff1a;8080 和 6443。如果配置不当&#xff0c;可能会导致未授权访问的安全风险。 8080 端口…

Ansible批量配置服务器免密登录步骤详解

一、准备工作 192.168.85.138 安装ansible&#xff0c;计划配置到139的免密 192.168.85.139 待配置免密 1. 生成SSH密钥对 在Ansible控制节点生成密钥对&#xff0c;用于后续免密认证&#xff1a; ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa 全部回车默认&#xff0c;无…

游戏引擎学习第99天

仓库:https://gitee.com/mrxiao_com/2d_game_2 黑板&#xff1a;制作一些光场(Light Field) 当前的目标是为游戏添加光照系统&#xff0c;并已完成了法线映射&#xff08;normal maps&#xff09;的管道&#xff0c;但还没有创建可以供这些正常映射采样的光场。为了继续推进&…

纪念日倒数日项目的实现-【纪念时刻-时光集】

纪念日/倒数日项目的实现## 一个练手的小项目&#xff0c;uniappnodemysql七牛云。 在如今快节奏的生活里&#xff0c;大家都忙忙碌碌&#xff0c;那些具有特殊意义的日子一不小心就容易被遗忘。今天&#xff0c;想给各位分享一个“纪念日”项目。 【纪念时刻-时光集】 一…

yanshee机器人初次使用说明(备注)-PyCharm

准备 需要&#xff1a; 1&#xff0c;&#xff08;优必选&#xff09;yanshee机器人Yanshee 开发者说明 2&#xff0c;手机-联网简单操控 / HDMI线与显示器和键鼠标-图形化开发环境 / 笔记本&#xff08;VNC-内置图形化开发环境/PyCharm等平台&#xff09;。 3&#xff0c;P…

webshell通信流量分析

环境安装 Apatche2 php sudo apt install apache2 -y sudo apt install php libapache2-mod-php php-mysql -y echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php sudo ufw allow Apache Full 如果成功访问info.php&#xff0c;则环境安…

uniapp - iconfont下载本地并且运用至项目上

1、项目中创建一个文件夹放置iconfont相关文件&#xff0c;例如src/assets/iconfont&#xff08;名称自己定义&#xff09; 2、在iconfont下载项目至本地 3、解压后把文件复制进1的文件夹中 4、修改src/assets/iconfont - iconfont.css里的font-face的src地址&#xff0c;修…

黑马Redis详细笔记(实战篇---短信登录)

目录 一.短信登录 1.1 导入项目 1.2 Session 实现短信登录 1.3 集群的 Session 共享问题 1.4 基于 Redis 实现共享 Session 登录 一.短信登录 1.1 导入项目 数据库准备 -- 创建用户表 CREATE TABLE user (id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 用户ID,phone …

企业级高并发全链路优化:流量分发、边缘防护与服务治理的整合之道

文章目录 第一章&#xff1a;引入概览1.1 高并发时代的业务挑战与背景1.2 全链路思维在高并发架构中的必要性1.3 解决方案总览&#xff1a;技术演进与混合架构模式 第二章&#xff1a;流量分发与边缘网络2.1 DNS 解析与全球流量调度2.2 LVS 与 Nginx 集群&#xff1a;流量负载均…