Codeforces Round 955 E. Number of k-good subarrays【分治、记忆化】

E. Number of k-good subarrays

E

题意

定义 b i t ( x ) bit(x) bit(x) x x x 的二进制表示下 1 1 1 的数量
一个数组的子段被称为 k − g o o d k-good kgood 的当且仅当:对于这个子段内的每个数 x x x,都有 b i t ( x ) ≤ k bit(x) \leq k bit(x)k

现在给定一个长度为 n n n 的数组 a a a,且 ∀ 0 ≤ i < n , a i = i \forall 0 \leq i < n, a_i = i ∀0i<n,ai=i,即 a = { 0 , 1 , 2 , . . . n − 1 } a = \{0, 1, 2, ... n - 1\} a={0,1,2,...n1}

求出 a a a k − g o o d k-good kgood 的子段数量

思路

首先我们观察发现:可以先将原数组选出连续的若干段,使得每一段都是极大的 k − g o o d k-good kgood 子段,也就是不能再往两边扩了。假设这一段的长度为 l e n len len,那么这一段对答案的贡献是: C l e n + 1 2 C_{len+1} ^ 2 Clen+12

由于问题规模过大,我们考虑分治
定义 f ( n , k ) f(n, k) f(n,k) 为在 [ 0 , n − 1 ] [0, n - 1] [0,n1] 中的 k − g o o d k-good kgood 子段数量,这个子状态返回一个元组 { r e s , l , r } \{res, l, r\} {res,l,r}

  • r e s res res 表示 [ 0 , n − 1 ] [0, n - 1] [0,n1] 里符合条件的子段数量
  • l l l 表示从头开始的最长连续 k − g o o d k-good kgood 长度
  • r r r 表示从尾开始的最长连续 k − g o o d k-good kgood 长度

我们再找到一个最大 m m m,使得 2 m < n 2^m < n 2m<n,即 2 m ≤ n − 1 2 ^ m \leq n - 1 2mn1
并将 [ 0 , n − 1 ] [0, n - 1] [0,n1] 分成两段: [ 0 , 2 m − 1 ] [0, 2 ^ m - 1] [0,2m1] [ 2 m , n − 1 ] [2^m, n - 1] [2m,n1]
我们发现第一段其实就是子问题 f ( 2 m , k ) f(2 ^ m, k) f(2m,k),那么第二段呢?它并不从零开始,好像无法转换成某一个子状态。

__builtin_clzll ( n ) 可以算出 n n n前导 0 0 0 数量

其实 2 m 2^m 2m 的最高位一定是和 n − 1 n - 1 n1 的最高位相同的,那么我们就等价于提前为第 m m m 为预定了一个 1 1 1,第二段就转换成了子状态: f ( n − 2 m , k − 1 ) f(n - 2^m, k - 1) f(n2m,k1)

因此, f ( n , k ) = f ( 2 m , k ) + f ( n − 2 m , k − 1 ) f(n, k) = f(2 ^ m, k) + f(n - 2 ^ m, k - 1) f(n,k)=f(2m,k)+f(n2m,k1)

不难发现,第二部分的复杂度为 O ( log ⁡ n ) O(\log n) O(logn),而第一部分由于它的第一个分量永远为 2 2 2 的整数次幂,因此第一部分最多有 O ( k ⋅ log ⁡ n ) O(k \cdot \log n) O(klogn) 种状态,我们可以使用记忆化加速搜索

当我们得到两个部分的返回 { r e s 1 , l 1 , r 1 } \{res_1, l_1, r_1 \} {res1,l1,r1} { r e s 2 , l 2 , r 2 } \{res_2, l_2, r_2 \} {res2,l2,r2} 之后,我们可以归并答案,由于之前我们把 r 1 r_1 r1 向前延伸和 l 2 l_2 l2 向后延伸的算在了 r e s 1 res_1 res1 r e s 2 res_2 res2 里,因此我们在合并中间的连续段的时候(合二为一),需要减掉之前的错误统计。

r e s = r e s 1 + r e s 2 − C r 1 + 1 2 − C l 2 + 1 2 + C r 1 + l 2 + 1 2 res = res_1 + res_2 - C_{r_1 + 1}^2 - C_{l_2 + 1}^2 + C_{r_1 + l_2 + 1}^2 res=res1+res2Cr1+12Cl2+12+Cr1+l2+12

#include<bits/stdc++.h>
#define fore(i,l,r)	for(int i=(int)(l);i<(int)(r);++i)
#define fi first
#define se second
#define endl '\n'
#define ull unsigned long long
#define ALL(v) v.begin(), v.end()
#define Debug(x, ed) std::cerr << #x << " = " << x << ed;const int INF=0x3f3f3f3f;
const long long INFLL=1e18;typedef long long ll;template<class T>
constexpr T power(T a, ll b){T res = 1;while(b){if(b&1) res = res * a;a = a * a;b >>= 1;}return res;
}constexpr ll mul(ll a,ll b,ll mod){ //快速乘,避免两个long long相乘取模溢出ll res = a * b - ll(1.L * a * b / mod) * mod;res %= mod;if(res < 0) res += mod; //误差return res;
}template<ll P>
struct MLL{ll x;constexpr MLL() = default;constexpr MLL(ll x) : x(norm(x % getMod())) {}static ll Mod;constexpr static ll getMod(){if(P > 0) return P;return Mod;}constexpr static void setMod(int _Mod){Mod = _Mod;}constexpr ll norm(ll x) const{if(x < 0){x += getMod();}if(x >= getMod()){x -= getMod();}return x;}constexpr ll val() const{return x;}explicit constexpr operator ll() const{ return x; //将结构体显示转换为ll类型: ll res = static_cast<ll>(OBJ)}constexpr MLL operator -() const{ //负号,等价于加上ModMLL res;res.x = norm(getMod() - x);return res;}constexpr MLL inv() const{assert(x != 0);return power(*this, getMod() - 2); //用费马小定理求逆}constexpr MLL& operator *= (MLL rhs) & { //& 表示“this”指针不能指向一个临时对象或const对象x = mul(x, rhs.x, getMod()); //该函数只能被一个左值调用return *this;}constexpr MLL& operator += (MLL rhs) & {x = norm(x + rhs.x);return *this;}constexpr MLL& operator -= (MLL rhs) & {x = norm(x - rhs.x);return *this;}constexpr MLL& operator /= (MLL rhs) & {return *this *= rhs.inv();}friend constexpr MLL operator * (MLL lhs, MLL rhs){MLL res = lhs;res *= rhs;return res;}friend constexpr MLL operator + (MLL lhs, MLL rhs){MLL res = lhs;res += rhs;return res;}friend constexpr MLL operator - (MLL lhs, MLL rhs){MLL res = lhs;res -= rhs;return res;}friend constexpr MLL operator / (MLL lhs, MLL rhs){MLL res = lhs;res /= rhs;return res;}friend constexpr std::istream& operator >> (std::istream& is, MLL& a){ll v;is >> v;a = MLL(v);return is;}friend constexpr std::ostream& operator << (std::ostream& os, MLL& a){return os << a.val();}friend constexpr bool operator == (MLL lhs, MLL rhs){return lhs.val() == rhs.val();}friend constexpr bool operator != (MLL lhs, MLL rhs){return lhs.val() != rhs.val();}
};const ll mod = 1e9 + 7;
using Z = MLL<mod>;const ll INV = 500000004ll; //2的逆元std::map<std::pair<ll, int>, std::tuple<Z, ll, ll>> mem; //记忆化std::tuple<Z, ll, ll> dfs(ll n, int k){if(k < 0)   return {0, 0, 0};if(n == 1)  return {1, 1, 1}; //小于1只有0int m = 63 - __builtin_clzll(n);ll mid = 1ll << m;if(mid == n){--m;mid >>= 1;if(mem.count({n, k})) return mem[{n, k}];}auto [res1, l1, r1] = dfs(mid, k);auto [res2, l2, r2] = dfs(n - mid, k - 1);Z w1 = Z(r1) * (r1 + 1) * INV;Z w2 = Z(l2) * (l2 + 1) * INV;Z tmp(r1 + l2);Z res = res1 + res2 - w1 - w2 + tmp * (tmp + 1) * INV;ll l = l1, r = r2;if(l1 == mid) l += l2;if(r2 == n - mid)   r += r1;if((mid << 1) == n) mem[{n, k}] = {res, l, r};return {res, l, r};
}int main(){std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout.tie(nullptr);int t;std::cin >> t;while(t--){ll n;int k;std::cin >> n >> k;auto [ans, l, r] = dfs(n, k);std::cout << ans << endl;}return 0;
}

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

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

相关文章

鸿蒙开发管理:【@ohos.account.distributedAccount (分布式帐号管理)】

分布式帐号管理 本模块提供管理分布式帐号的一些基础功能&#xff0c;主要包括查询和更新帐号登录状态。 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。开发前请熟悉鸿蒙开发指导文档&#xff…

自动化设备上位机设计 四

目录 一 设计原型 二 后台代码 一 设计原型 二 后台代码 using SimpleTCP; using SqlSugar; using System.Text;namespace 自动化上位机设计 {public partial class Form1 : Form{SqlHelper sqlHelper new SqlHelper();SqlSugarClient dbContent null;bool IsRun false;i…

论文翻译 | (DSP)展示-搜索-预测:为知识密集型自然语言处理组合检索和语言模型

摘要 检索增强式上下文学习已经成为一种强大的方法&#xff0c;利用冻结语言模型 (LM) 和检索模型 (RM) 来解决知识密集型任务。现有工作将这些模型结合在简单的“检索-读取”流程中&#xff0c;其中 RM 检索到的段落被插入到 LM 提示中。 为了充分发挥冻结 LM 和 RM 的…

# Sharding-JDBC 从入门到精通(9)- 综合案例(二)添加商品

Sharding-JDBC 从入门到精通&#xff08;9&#xff09;- 综合案例&#xff08;二&#xff09;添加商品 一、Sharding-JDBC 综合案例-添加商品-dao 1、在 shopping 子工程&#xff08;子模块&#xff09;中&#xff0c;创建 dao 接口类 ProductDao.java /*** dbsharding\sh…

基于深度学习LightWeight的人体姿态之行为识别系统源码

一. LightWeight概述 light weight openpose是openpose的简化版本&#xff0c;使用了openpose的大体流程。 Light weight openpose和openpose的区别是&#xff1a; a 前者使用的是Mobilenet V1&#xff08;到conv5_5&#xff09;&#xff0c;后者使用的是Vgg19&#xff08;前10…

哈希表——C语言

哈希表&#xff08;Hash Table&#xff09;是一种高效的数据结构&#xff0c;能够在平均情况下实现常数时间的查找、插入和删除操作。 哈希表的核心是哈希函数&#xff0c;哈希函数是一个将输入数据&#xff08;通常称为“键”或“key”&#xff09;转换为固定长度的整数的函数…

Efficient Contrastive Learning for Fast and Accurate Inference on Graphs

发表于:ICML24 推荐指数: #paper/⭐⭐⭐ 创新点一颗星,证明三颗星(证明的不错,值得借鉴,但是思路只能说还行吧) 如图, 本文采取的创新点就是MLP用原始节点,GCN用邻居节点的对比学习.这样,可以加快运算速度 L E C L − 1 ∣ V ∣ ∑ v ∈ V 1 ∣ N ( v ) ∣ ∑ u ∈ N ( v )…

k8s 部署 springboot 项目内存持续增长问题分析解决

写在前面 工作中遇到&#xff0c;请教公司前辈解决&#xff0c;简单整理记忆博文内容涉及一次 GC 问题的分析以及解决理解不足小伙伴帮忙指正 &#x1f603;,生活加油 99%的焦虑都来自于虚度时间和没有好好做事&#xff0c;所以唯一的解决办法就是行动起来&#xff0c;认真做完…

语音识别FBank特征提取学习笔记

语音识别就是把一段语音信号转换成对应的文本信息&#xff0c;这一过程包括四个大的模块&#xff0c;分别是&#xff1a;特征提取、声学模型、语言模型、字典与解码。 本篇就来梳理一下特征提取模块的实现思路和方法。 常用的语音特征有&#xff1a; 梅尔频率倒谱系数&#x…

学生管理系统(通过顺序表,获取连续堆区空间实现)

将学生的信息&#xff0c;以顺序表的方式存储&#xff08;堆区&#xff09;&#xff0c;并且实现封装函数 &#xff1a; 1】顺序表的创建&#xff0c; 2】判满、 3】判空、 4】往顺序表里增加学生信息、 5】遍历学生信息 6】任意位置插入学生信息 7】任意位置删除学生信…

0301STM32GPIO外设输出

STM32GPIO外设输出 STM32内部的GPIO外设GPIO简介基本结构GPIO位结构输入部分&#xff1a;输出部分&#xff1a; GPIO八种工作模式浮空/上拉/下拉输入模拟输入开漏/推挽输出复用开漏/推挽输出 手册寄存器描述GPIO功能描述外设的GPIO配置GPIO寄存器描述端口输入数据寄存器端口输出…

QT入门笔记-自定义控件封装 30

具体代码如下: QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c17# You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES QT_DISABLE_DEPRECATED_BEFORE0x060000 …

并查集(还有反集也在)

一.定义 定义&#xff1a; 并查集是一种树型的数据结构&#xff0c;用于处理一些不相交集合的合并及查询问题&#xff08;即所谓的并、查&#xff09;。比如说&#xff0c;我们可以用并查集来判断一个森林中有几棵树、某个节点是否属于某棵树等。 主要构成&#xff1a; 并查集…

Android计算器界面的设计——表格布局TableLayout实操

目录 任务目标任务分析任务实施 任务目标 使用TextView、Button等实现一个计算器界面&#xff0c;界面如图1所示。 图1 计算器界面效果图 任务分析 界面整体使用表格布局&#xff0c;第一行使用一个TextView控件&#xff0c;横跨4列&#xff0c;中间4行4列&#xff0c;最后一…

io流 多线程

目录 一、io流 1.什么是io流 2.流的方向 i.输入流 ii.输出流 3.操作文件的类型 i.字节流 1.拷贝 ii.字符流 ​3.字符流输出流出数据 4.字节流和字符流的使用场景 5.练习 6.缓冲流 1.字节缓冲流拷贝文件 2.字符缓冲流特有的方法 1.方法 2.总结 7.转换流基本用法…

第2集《修习止观坐禅法要》

请打开补充讲表第一面&#xff0c;附表一、念佛摄心方便法。 我们前面讲到修止&#xff0c;就是善取所缘境的相貌&#xff0c;然后心于所缘&#xff0c;专一安住&#xff1b;心于所缘&#xff0c;相续安住&#xff1b;达到心一境性的目的。 站在修学净土的角度&#xff0c;他…

《C语言》预处理

文章目录 一、预定义符号二、#define定义常量三、#define定义宏四、宏更函数的对比五、#和##1、#运算符2、##运算符 一、预定义符号 C语言设置了一些预定义符号&#xff0c;可以直接使用&#xff0c;在预处理期间进行处理的。 __FILE__//进行编译的源文件 __LINE__//文件当前的…

【数据结构与算法】插入排序

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注 ​

人工智能、机器学习、神经网络、深度学习和卷积神经网络的概念和关系

人工智能&#xff08;Artificial Intelligence&#xff0c;缩写为AI&#xff09;--又称为机器智能&#xff0c;是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。 人工智能是智能学科重要的组成部分&#xff0c;它企图了解智能的实质…

【问题解决】 pyocd 报错 No USB backend found 的解决方法

pyocd 报错 No USB backend found 的解决方法 本文记录了我在Windows 10系统上遇到的pyocd命令执行报错——No USB backend found 的分析过程和解决方法。遇到类似问题的朋友可以直接参考最后的解决方法&#xff0c;向了解问题发送原因的可以查看原因分析部分。 文章目录 pyoc…