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

2023NOIP A层联测18 划分

题目大意

对于一个长度为 n n n 01 01 01字符串 S S S,请求出将其分为至少 k k k段,将每段看成二进制数求和后的最大值以及取到这个最大值的划分方案的数量。

输出最大值模 998244353 998244353 998244353后的值和划分方案的数量模 998244353 998244353 998244353后的值。

1 ≤ n , k ≤ 2 × 1 0 6 1\leq n,k\leq 2\times 10^6 1n,k2×106


题解

如果前 k k k位没有 1 1 1,则最优解一定是第一个 1 1 1之前所有间隔中选 k − 1 k-1 k1个及以上的间隔(因为把最后一段形成的二进制数从中间分开一定会减小),可以用组合数来计算。如果一个 1 1 1都没有,则最优解就是 n − 1 n-1 n1个间隔中选 k − 1 k-1 k1个及以上的间隔。

如果不满足上面的条件,则最优解一定是选出一段长度为 n − k + 1 n-k+1 nk+1子串,剩下的每一个数单独分一段。我们考虑比较两种划分方案的大小。

设第一种划分方案的 n − k + 1 n-k+1 nk+1的串看成的二进制数为 v 1 v_1 v1,其余 k − 1 k-1 k1段中 1 1 1的个数为 t 1 t_1 t1,第二种划分方案的 n − k + 1 n-k+1 nk+1的串看成的二进制数为 v 2 v_2 v2,其余 k − 1 k-1 k1段中 1 1 1的个数为 t 2 t_2 t2。当 v 1 > v 2 v_1>v_2 v1>v2

  • 如果 v 1 v_1 v1 v 2 v_2 v2的前 n − k n-k nk位相同,而 v 1 v_1 v1的最后一位为 1 1 1 v 2 v_2 v2的最后一位为 0 0 0,则 t 1 + 1 = t 2 t_1+1=t_2 t1+1=t2,两种划分方案的结果是相同的
  • 如果 v 1 v_1 v1 v 2 v_2 v2的前 n − k n-k nk位存在不同,则设第一个不同的位为 t t t
    • 如果 t 1 ≥ t 2 t_1\geq t_2 t1t2,则显然第一种方案更优
    • 如果 t 1 < t 2 t_1<t_2 t1<t2,则我们将 S S S中的每个 1 1 1减去对答案的贡献 1 1 1,两种划分方案的大小关系不变。此时其余 k − 1 k-1 k1段中的 1 1 1都不算贡献,最大段中每一个为 1 1 1的位 i i i的贡献为 2 i − 1 2^i-1 2i1,那么两种方案中前 t − 1 t-1 t1个位置的贡献相同,第一种方案中第 t t t位的贡献为 2 t − 1 2^t-1 2t1,而第二种划分方案中第 t t t位为 0 0 0,之后的位之和小于等于 2 t − 1 2^t-1 2t1,因为每个 1 1 1的贡献都被减去了 1 1 1,所以之后的位的贡献之和小于 2 t − 1 2^t-1 2t1,得第一种方案更优

由此可得,以 1 , 2 , … , k 1,2,\dots,k 1,2,,k开头,长度为 n − k + 1 n-k+1 nk+1的串中,划分出的串为字典序最大的串的结果最优。如果字典序最大的串的最后一位为 1 1 1,前面 n − k n-k nk位与其相同,最后一位为 0 0 0的串也是最优的。

那我们怎么求字典序最大的串呢?可以用二分哈希。从 1 1 1 k k k枚举 i i i,设 l l l为以 1 1 1 i − 1 i-1 i1为起点的串中字典序最大的串的起点,那么对于当前的 i i i,我们要比较 l l l开头的串和 i i i开头的串的字典序的大小。那么,我们可以二分两个串最长的公共前缀,假设公共前缀为 1 1 1 t t t,则 t + 1 t+1 t+1即为两个串中第一个不同的位置,比较这个位置的大小即可知道两个串的大小关系。用哈希可以 O ( 1 ) O(1) O(1)判断两个字符串是否相同,所以处理一个 i i i的时间复杂度是 O ( log ⁡ n ) O(\log n) O(logn)的。

求出字典序最大的串之后,判断这个串的最后一位是否为 1 1 1。如果是的话,将 1 1 1改为 0 0 0,再判断以 1 , 2 , … , k 1,2,\dots,k 1,2,,k开头,长度为 n − k + 1 n-k+1 nk+1的串中是否有与这个修改后的串相同的,这同样可以用哈希来 O ( 1 ) O(1) O(1)比较。

最大值可以用字典序最大的串对应的二进制数加其余部分的 1 1 1的个数来得到,方案数可以在比较大小和是否相同的时候得到,那么这道题就解决了。

注意要特判 n = = k n==k n==k的情况,此时最大值为 S S S 1 1 1的个数,方案数为 1 1 1

注意代码中虽然使用了单哈希,但这样有一定可能将两个不同的串判断为相同的串(有可能,但可能性不大),所以最好使用双哈希。

时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)

code

#include<bits/stdc++.h>
using namespace std;
const int N=2000000;
const long long mod=998244353;
int n,k,len,sum[N+5];
long long ans1,ans2,p[N+5],pw[N+5],jc[N+5],ny[N+5];
char s[N+5];
long long mi(long long t,long long v){if(!v) return 1;long long re=mi(t,v/2);re=re*re%mod;if(v&1) re=re*t%mod;return re;
}
void init(){jc[0]=1;pw[0]=1;for(int i=1;i<=N;i++){jc[i]=jc[i-1]*i%mod;pw[i]=pw[i-1]*2%mod;}ny[N]=mi(jc[N],mod-2);for(int i=N-1;i>=0;i--) ny[i]=ny[i+1]*(i+1)%mod;
}
long long C(int x,int y){return jc[x]*ny[y]%mod*ny[x-y]%mod;
}
long long hsh(int l,int r){return (p[r]-p[l-1]*pw[r-l+1]%mod+mod)%mod;
}
int gt(int i,int j){int l=1,r=len,mid;while(l<=r){mid=l+r>>1;if(hsh(i,i+mid-1)==hsh(j,j+mid-1)) l=mid+1;else r=mid-1;}return l-1;
}
int main()
{
//	freopen("divide.in","r",stdin);
//	freopen("divide.out","w",stdout);init();scanf("%d%d",&n,&k);len=n-k+1;scanf("%s",s+1);for(int i=1;i<=n;i++){sum[i]=sum[i-1]+s[i]-'0';p[i]=(p[i-1]*2+s[i]-'0')%mod;}if(!sum[n]){for(int i=k;i<=n;i++){ans2=(ans2+C(n-1,i-1))%mod;}printf("0 %lld",ans2);return 0;}if(k==n){printf("%lld 1",sum[n]);return 0;}if(sum[n-len+1]==0){int fst=1;while(s[fst]!='1') ++fst;ans1=hsh(fst,n);for(int i=k;i<=fst;i++){ans2=(ans2+C(fst-1,i-1))%mod;}printf("%lld %lld",ans1,ans2);return 0;}int l=1;ans2=1;for(int i=2;i+len-1<=n;i++){int vt=gt(l,i);if(vt==len) ++ans2;else if(s[l+vt]<s[i+vt]){l=i;ans2=1;}}if(s[l+len-1]=='1'){int hs=(hsh(l,l+len-1)-1)%mod;for(int i=1;i+len-1<=n;i++){if(hs==hsh(i,i+len-1)) ++ans2;}}ans1=hsh(l,l+len-1)+sum[l-1]+sum[n]-sum[l+len-1];printf("%lld %lld",ans1,ans2);return 0;
}
http://www.lryc.cn/news/207132.html

相关文章:

  • pc与android设备进行通信
  • 【网安大模型专题10.19】论文6:Java漏洞自动修复+数据集 VJBench+大语言模型、APR技术+代码转换方法+LLM和DL-APR模型的挑战与机会
  • const 和 volatile 在实例成员函数的应用
  • 比Nginx测试桩更方便,ShenYu网关的Mock插件
  • IDEA: 自用主题及字体搭配推荐
  • Qt中的枚举变量,Q_ENUM,Q_FLAG以及Qt中自定义结构体、枚举型做信号参数传递
  • 【C++】priority_queue仿函数
  • 如何驾驭ChatGPT:掌控有效对话!
  • LeetCode 面试题 16.03. 交点
  • 【码银送书第九期】《ChatGPT 驱动软件开发:AI 在软件研发全流程中的革新与实践》
  • Hadoop3.0大数据处理学习4(案例:数据清洗、数据指标统计、任务脚本封装、Sqoop导出Mysql)
  • 华为机试题:HJ3 明明的随机数
  • Python OpenCV将n×n的小图拼接成m×m的大图
  • wkhtmltoimage/wkhtmltopdf 使用实践
  • Rclone连接Onedrive
  • RK356X/RK3588构建Ubuntu20.04根文件系统
  • 本地新建项目如何推到码云上去
  • RSAUtil 前端 JavaScript JSEncrypt 实现 RSA (长文本)加密解密
  • uniapp map polygons 区域填充色(fillColor)在ios显示正常,但在安卓手机显示是黑色的,怎么解决?
  • OSCAR数据库上锁问题如何排查
  • FPGA与人工智能泛谈-01
  • 【VASP】POTCAR文件
  • 棒球俱乐部青少年成长体系·棒球1号位
  • 折叠式菜单怎么做编程,初学编程系统化教程初级1上线
  • 与AI对话,如何写好prompt?
  • 基于YOLOv8模型和UA-DETRAC数据集的车辆目标检测系统(PyTorch+Pyside6+YOLOv8模型)
  • 0037【Edabit ★☆☆☆☆☆】【修改Bug 2】Buggy Code (Part 2)
  • 【算法中的Java】— 判断语句
  • 【单例模式】饿汉式,懒汉式?JAVA如何实现单例?线程安全吗?
  • Spark_SQL-DataFrame数据写出以及读写数据库(以MySQl为例)