Shuffle 题解
题目大意
给定一个长度为 \(n\) 的 01 序列 \(a\),你可以进行至多一次以下操作:
- 选定 \(a\) 的一个连续段,满足连续段内恰好有 \(k\) 个 \(1\),将该连续段任意排列。
问能产生多少种不同的 01 序列。
思路分析
(这题 \(n\) 完全可以开到 \(10^6\) 或是 \(10^7\),因为存在 \(O(n)\) 的做法。)
考虑 DP。
设 \(f_i\) 表示只考虑 \(1\sim i\) 中的字符,能产生多少种不同的 01 序列。
那么可以列出 DP 方程:
\]
其中,\(m\) 是 \(i\) 往左的极长 \(k\) 个 \(1\) 的连续段的长度。
解释一下:
我们在考虑 \(f_{i-1}\) 时,是把 \(s_i\) 恒定为 \(s_i\) 做的,而在考虑 \(f_i\) 时为了避免算重,我们强制钦定在 \(i\) 的位置放 \(s_i\) 的相反的数,也就是说,若 \(s_i=0\),我们强制这个位置放 \(1\),那么方案数就是 \({m-1\choose k-1}\),在前 \(m-1\) 个位置上放剩下的 \(k-1\) 个数。\(s_i=1\) 类似。
注意初值,当 \(m\) 第一次存在时,\(f_i={m\choose k}\),这是因为 \(f_i\) 前面没有人算它的重。
实现方式有很多种,我使用了二分实现,时间复杂度为 \(O(n\log n)\)。
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
using namespace std;
const int N = 1001000, L = 1000000, mod = 998244353;
#define inf 0x3f3f3f3f
#define int long long
int n, k, ans;
int fac[N], inv[N], sum[N];
set <int> S;
char s[N];
int q_pow(int a, int b){
int res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
int C(int n, int m){
if (n < m) return 0;
return fac[n] * inv[n - m] % mod * inv[m] % mod;
}
int find(int s, int k){ // 找到从 s 往左的第 k + 1 个 1 的位置的右边
if (sum[s] < k) return inf;
int l = 1, r = s, ans = 1;
while (l <= r) {
int mid = (l + r) >> 1;
if (sum[s] - sum[mid - 1] <= k) r = mid - 1, ans = mid;
else l = mid + 1;
}
return *(--S.lower_bound(ans)) + 1;
}
signed main(){
fac[0] = 1;
for (int i = 1; i <= L; i ++) fac[i] = fac[i - 1] * i % mod;
inv[L] = q_pow(fac[L], mod - 2);
for (int i = L; i >= 1; i --) inv[i - 1] = inv[i] * i % mod;
scanf("%lld %lld", &n, &k);
scanf("%s", s + 1);
for (int i = 1; i <= n; i ++) sum[i] = sum[i - 1] + (s[i] == '1');
S.insert(0);
for (int i = 1; i <= n; i ++) if (s[i] == '1') S.insert(i);
int flag = 0;
for (int i = 1; i <= n; i ++) {
if (sum[i] == k && !flag) ans = (ans + C(i, k)) % mod, flag = 1;
else ans = (ans + C(i - find(i, k), k - (s[i] == '0'))) % mod;
}
if (!flag) ans = 1;
cout << ans << '\n';
return 0;
}
Shuffle 题解的更多相关文章
- 算法与数据结构基础 - 贪心(Greedy)
贪心基础 贪心(Greedy)常用于解决最优问题,以期通过某种策略获得一系列局部最优解.从而求得整体最优解. 贪心从局部最优角度考虑,只适用于具备无后效性的问题,即某个状态以前的过程不影响以后的状态. ...
- 【LeetCode】随机化算法 random(共6题)
[384]Shuffle an Array(2019年3月12日) Shuffle a set of numbers without duplicates. 实现一个类,里面有两个 api,struc ...
- 1965: [Ahoi2005]SHUFFLE 洗牌
1965: [Ahoi2005]SHUFFLE 洗牌 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 408 Solved: 240[Submit][St ...
- 算法(第四版)C# 习题题解——3.1
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 查找更方便的版本见:https ...
- 算法(第四版)C# 习题题解——2.3
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 查找更为方便的版本见:http ...
- 算法(第四版)C# 习题题解——2.2
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 查找更为方便的版本见:http ...
- 算法(第四版)C# 习题题解——2.1
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 这一节内容可能会用到的库文件有 ...
- 算法(第四版)C# 习题题解——1.3
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 这一节内容可能会用到的库文件有 ...
- POJ 3078 - Shuffle'm Up - [模拟题]
题目链接:http://poj.org/problem?id=3087 Description A common pastime for poker players at a poker table ...
- 算法(第四版)C# 习题题解——1.1
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 善用 Ctrl + F 查找题 ...
随机推荐
- 用postman模拟“授权代码授予”模式下获取Azure的用户信息(UserInfo)
用postman模拟"授权代码授予"模式下获取Azure的用户信息(UserInfo) 1. 准备参数: 图1: 图2: 2. 调用: 点击按钮"Get New Acce ...
- redis集群报错:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk.
之前在x86架构的服务器部署redis集群,未遇到题中问题:然而在ARM架构的服务器部署redis集群,第一次遇到如此问题.虽然问题已经解决,但不清楚问题的具体原因,在此做个记录. 性能测试过程中,通 ...
- ArcMap镶嵌数据集的创建、数据导入与数据范围修改方法
本文介绍基于ArcMap软件,建立镶嵌数据集(Mosaic Datasets).导入栅格图像数据,并调整像元数值范围的方法. 镶嵌数据集(Mosaic Datasets)是一种用以管理.显示. ...
- 使用Stable Diffusion生成艺术二维码
在数字艺术的世界中,二维码已经从单纯的信息承载工具转变为可以展示艺术表达的媒介.这是通过使用Stable Diffusion的技术实现的,它可以将任何二维码转化为独特的艺术作品.接下来,我们将一步步教 ...
- 基于.Net Core实现的飞书文档一键导出服务(支持多系统)
feishu-doc-export 一个支持Windows.Mac.Linux系统的飞书文档一键导出服务,仅需一行命令即可将飞书知识库的全部文档同步到本地电脑.导出速度嘎嘎快,实测700多个文档导出只 ...
- LEA: Improving Sentence Similarity Robustness to Typos Using Lexical Attention Bias 论文阅读
LEA: Improving Sentence Similarity Robustness to Typos Using Lexical Attention Bias 论文阅读 KDD 2023 原文 ...
- CF1654E Arithmetic Operations 题解
摘自我的洛谷博客. 题目让我们求改变数字的最少次数,那我们转化一下, 求可以保留最多的数字个数 \(cnt\),再用 \(n\) 减一下就行,即 \(res = n - cnt\). 我们先考虑两种暴 ...
- 如何新建一个django项目
1.新建项目 2选择django 3.接下来我们进入 djangotest目录输入以下命令,启动服务器: python manage.py runserver 0.0.0.0:8000 0.0.0.0 ...
- linux 字符集与编码格式相关
字符集:多个字符的集合. # 书写系统字母与符号的集合. 字符编码:把 字符集 中的字符 编码为(映射)指定集合中的某一对象. # 以便文本在计算机中存储和通过通信网络的传递 查看文件的的编码格式 ...
- Fastjson1.2.24漏洞复现-基于vulhub漏洞平台(文件上传写入-反弹shell)
Fastjson1.2.24漏洞复现-基于vulhub漏洞平台 环境准备: 192.168.59.130 攻击机 window10 192.168.59.135 靶机 centos8 声明:不涉及互联 ...