当前位置: 首页 > news >正文

书架排列问题(区间查询)

大家好,am是金奇人生,话不多说,讲题吧!

说明

在一个图书馆整理活动中,管理员需要将两种颜色的书籍(红色和蓝色)排列在书架上。规则如下:

1.蓝色书籍每次必须连续摆放恰好 k 本。

2.红色书籍每次可以单独摆放,也可以连续摆放任意数量。

管理员需要计算书架长度在 [l,r] 范围内的所有合法排列方案数,结果对109+7 取模。

输入格式

第一行包含两个整数 $t$ 和 $k$($1 \le t \le 1e5,1 \le k \le 1e5$),表示测试用例数量和每组蓝色书籍的固定长度。

接下来 t 行,每行包含两个整数 l 和 r(1≤l≤r≤1e6),表示查询的区间。

输出格式

对于每个查询,输出一个整数,表示合法方案数模 $10^9+7$ 的结果。

输入样例1

3 2 1 3 2 3 4 4
输出样例1
6 5 5

提示

样例解释

当 k=2 时:

长度为 1 时,只能是红色书籍(1 种)。

长度为 2 时,可能是 RR 或 BB(2 种)。

长度为 3 时,可能的组合有 RRR、RBB、BBR(3 种),总共有 1+2+3=6 种。

数据范围

50% 数据 t≤100,1≤l≤r≤1e5

100% 数据 t≤1000000,1≤l≤r≤1e6

#include<bits/stdc++.h> using namespace std; int t,k,f[1000005]; int qian[1000005]; int main() { cin>>t>>k; f[0]=1; for(int i=1; i<=1000000; i++){ f[i]+=f[i-1]; if(i>=k)f[i]=(f[i]+f[i-k])%1000000007; } for(int i=1; i<=1000000; i++) qian[i]=(qian[i-1]+f[i])%1000000007; int l,r; while(t--){ cin>>l>>r; cout<<(qian[r]-qian[l-1]+1000000007)%1000000007<<endl; } return 0; }

1. 状态定义与转移方程

我们需要计算长度为 ii 的书架有多少种合法排列,设数组f[i]表示这个数量。

对于长度为 ii 的书架,最后放置的书只有两种情况:

  1. 以红色书结尾‌:红色书可以单独放,也可以连续放。如果最后一位是红色,那么前 i−1i−1 位只要是合法排列即可。因此,这种情况贡献的方案数是f[i-1]
  2. 以蓝色书结尾‌:题目规定蓝色书必须‌恰好连续摆放 kk 本‌。这意味着如果书架以蓝色结尾,那么最后 kk 个位置必须全部是蓝色,且这 kk 本蓝色书作为一个整体,其前面的 i−ki−k 个位置必须是合法排列。因此,这种情况贡献的方案数是f[i-k](前提是 i≥ki≥k)。

综合起来,状态转移方程为:
f[i]=f[i−1]+f[i−k](当 i≥k)f[i]=f[i−1]+f[i−k](当 i≥k)
f[i]=f[i−1](当 i<k)f[i]=f[i−1](当 i<k)

边界条件‌:f = 1。这代表长度为 0 时有一种“空”的方案。这是为了处理当 i=ki=k 时,直接放置一组蓝色书的情况(即f[k] += f)。

2. 前缀和优化

题目要求查询区间 [l,r][l,r] 内所有长度方案数的总和。如果每次查询都循环累加,效率太低。我们可以预处理一个前缀和数组qian
qian[i]=∑j=1if[j]qian[i]=∑j=1i​f[j]

这样,对于每次查询 [l,r][l,r],答案就是:
Answer=qian[r]−qian[l−1]Answer=qian[r]−qian[l−1]

注意:在模运算中,减法可能导致负数,所以需要写成(qian[r] - qian[l-1] + MOD) % MOD

3. 代码实现:

#include<bits/stdc++.h> using namespace std; int t,k,f; int qian; int main() { cin>>t>>k; f[0]=1; // 第一步:动态规划计算每个长度的方案数 f[i] for(int i=1; i<=1000000; i++){ f[i]+=f[i-1]; // 情况1:最后放一本红色书 if(i>=k) f[i]=(f[i]+f[i-k])%1000000007; // 情况2:最后放 k 本蓝色书 } // 第二步:计算前缀和 qian[i] for(int i=1; i<=1000000; i++) qian[i]=(qian[i-1]+f[i])%1000000007; int l,r; // 第三步:处理查询 while(t--){ cin>>l>>r; // 利用前缀和差分计算区间和,注意处理负数取模 cout<<(qian[r]-qian[l-1]+1000000007)%1000000007<<endl; } return 0; }

关键点总结

  1. f=1的作用‌:它是递推的基石。例如当 i=ki=k 时,f[k]会加上f,这代表了“前0本书合法,紧接着放k本蓝书”这一种情况。
  2. 模运算处理‌:在累加f[i]和计算前缀和时都要随时取模,防止整数溢出。最后在输出结果时,通过+ 1000000007确保减法结果为非负数。
  3. 时间复杂度‌:预处理部分为 O(N)O(N),每次查询为 O(1)O(1),总复杂度为 O(N+T)O(N+T),完全满足 N=10,T=10N=10,T=10 的数据范围要求。

求关注,来之不易......

http://www.jsqmd.com/news/1402391/

相关文章:

  • OpenClaw Agent Send:命令行驱动的多平台消息自动化投递工具实战指南
  • Linux上安装FFmpeg
  • 宇树科技IPO启示:从技术期权到机器人商业化的硬科技创业逻辑
  • PostgreSQL笔记1:AI时代的数据底座——从趋势到实践的全面解读
  • 从信息熵到KL散度:深入理解Transformer损失函数的核心数学原理
  • 2026年8月全自动闪测仪/‌精密五金闪测仪厂家优选推荐_东莞市质伟捷达机械设备有限公司 - 品牌宣传支持者
  • 低压直流电机驱动优选|LTK118 单通道 H 桥驱动芯片,玩具 / 电动牙刷 / 电子锁全能适配
  • 银行流水模拟系统开发指南与实现方案
  • DeepSeek Harness 为什么敢说“一切皆插件“?拆透 Cordis 引擎的五大核心机制
  • 账房先生的数据库算盘:ArkTS 为鸿蒙记账本设计流水表与分类字典
  • Mac系统卡顿排查:搜狗输入法导致UI响应延迟的深度分析与解决方案
  • Go语言钉钉机器人插件ddingtalk实战:从入门到生产级告警系统构建
  • 2026年8月安徽非转基因菜籽油/安徽农家菜籽油优质厂家推荐_宁国市沙埠粮油加工厂 - 行业平台推荐
  • 检测机构查询小程序众多,哪家才是你的最优之选?
  • php内核源码解析=类型系统——PHP的类型到底怎么运作的
  • OpenAI 客户端取消传播连环炸:MCP Server 超时后我的重试逻辑为何雪崩
  • 企业级应用CLI化:从ChatDev看命令行工具在自动化工作流中的核心价值
  • 卢湾可靠的水利直缝管/Q355B-Z15钢板卷管有哪些 - 行业推荐官[官方】--
  • Windows批处理脚本权限与编码问题实战解决方案
  • T3Ster热瞬态测试:结构函数原理与IC热阻精准测量实战
  • Python高效操作Redis:从连接管理到性能优化的实战指南
  • Python 如何实现 AI API 的动态路由与多通道负载均衡:多账号与多供应商的高可用调度
  • Git安装与配置全指南:从入门到精通
  • 怎么下载并安装node.js 且 启动 12306-mcp
  • Haar小波子带剪枝:一种无需重训练的LLM后训练压缩实践指南
  • 从Codex用户流失看AI开发工具体验优化:安装、集成与长期维护
  • DMR 专网项目复盘:黑龙江某林区通信改造客户反馈记录
  • 开源船舶管理系统OpenShip:从架构设计到二次开发实战
  • 从OpenClaw实战看云服务CLI工具:自动化运维与DevOps效率提升
  • KaihongOS 桌面版原生 VS Code 上线