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

[模拟赛]拆分(div)

前言:

之前考过,现在被拿来作为DIV2的T3,给学第、学妹们考。回忆的时候对状态的设计没有太清晰还是写一下吧。

题面描述:

给定一个数 \(n\),你需要输出将 \(n\) 拆分成若干可重无序的二的次幂的方案数。答案对 \(10^9+7\) 取模。

解题思路:

首先有一个结论,那就是如果 \(n\)\(2^i\),那么分成大于等于两份的话,对拆分出来的的数排序后一定存在一个前缀和为 \(2^{i-1}\)

因为小于 \(2^i\) 的最大的 \(2\) 的整数次幂只有 \(2^{i-1}\),所以如果拆出 \(2^{i-1}\) 那么一定会有一个前缀和为 \(2^{i-1}\),如果不拆,那么只能拆更小的数,肯定能组成 \(2^{i-1}\)

所以设计状态,\(f_{i,j}\) 表示用 \(\le 2^{j}\) 的数组成 \(2^i\) 的方案数。

根据上面所说的结论,可以知道排完序后,存在一个前半部分和为 \(2^{i-1}\),后半部分和为 \(2^{i-1}\)

考虑 \(f_{i,j}\) 的值,转移枚举 \(k \le j\) 表示前半部分所用的数 \(\le 2^{k}\) 组成 \(2^{i-1}\) 的方案数,后半部分用区间 \([2^k, 2^j]\) 的数字组成 \(2^{i-1}\) 的方案数。\(f_{i,j}\) 为两部分的乘积。

前半部分是简单的,后半部分可以将所有数字 \(\div 2{k}\) 这样后半部分就变为了使用区间 \([1,2^{j-k}]\) 的数组成和为 \(2^{i-1-k}\) 的方案数了。即:

\[f_{i,j} \longleftarrow \sum _{k=0}^{j} f_{i-1,k} \times f_{i-1-k,j-k} \]

那么现在我们会做 \(n\)\(2\) 的整数次幂的情况了,考虑不是 \(2\) 的次幂的情况。

还有个结论,那就是一个数 \(n\) 拆分完后排序,一定存在一个前缀和为 \(lowbit(n)\)

考虑扩大范围,即排序后,一定存在一种划分方案,使得每段为 \(2^{a_{i}}\)\(a_{i}\)\(n\) 从低到高考虑第 \(i\) 个二进制为 \(1\) 的位置。

那么设计状态 \(g_{i,j}\) 表示用 \(\le 2^{j}\) 的数字拼出了最低的 \(i\)\(2\) 进制为 \(1\) 的位置的方案数。

推的方法同理。

\[g_{i,j} \longleftarrow \sum _{k=0}^{j} g_{i-1,k} \times f_{a_{i}-k,j-k} \]

时间复杂度: \(O(\log^3 n)\)

代码实现:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 70, mod = 1e9 + 7;
int n, m, tot, cnt, f[N][N], g[N][N], a[N];
void add(int &x, int y){x = (x + y) % mod;}
void solve(){cin >> n, cnt = tot = 0, m = log2(n);while(n){if(n & 1) a[++tot] = cnt;++cnt;n >>= 1;}for(int i = 0; i <= m + 1; i++)for(int j = 0; j <= m + 1; j++) f[i][j] = g[i][j] = 0;f[0][0] = 1;for(int i = 1; i <= m; i++){f[i][i] = 1;for(int j = 0; j <= i; j++){for(int k = 0; k <= j; k++)add(f[i][j], f[i - 1][k] * f[i - 1 - k][j - k] % mod);}}g[0][0] = 1;for(int i = 1; i <= tot; i++){for(int j = 0; j <= a[i]; j++){for(int k = 0; k <= j; k++){add(g[i][j], g[i - 1][k] * f[a[i] - k][j - k] % mod);}}}int ans = 0;for(int i = 0; i <= m; i++) add(ans, g[tot][i]);cout << ans << endl;
}
signed main(){freopen("div.in", "r", stdin);freopen("div.out", "w", stdout);int T;cin >> T;while(T--) solve();return 0;
}
http://www.rkmt.cn/news/60700.html

相关文章:

  • 详细介绍:【微服务组件】Springboot结合Dubbo实现RPC调用
  • 怎么理解np.array([10, 20]).reshape(-1, 1)?
  • 深入解析:网络安全等级保护测评高风险判定实施指引(试行)--2020与2025版对比
  • AI学习机值不值?2025年实测最有用的AI学习机品牌推荐!
  • 2025年11月机器人油脂公司推荐榜:精选五家优质供应商对比分析
  • hikivision 考勤机数据提取
  • [python] Python数据类使用指北
  • 深入解析:iOS 26 App 开发阶段性能优化 从多工具协作到数据驱动的实战体系
  • 小程序开发使用vant ui 组件快速开发
  • 课后作业8
  • 2025年11月25日加班
  • 租房买房必看1为什么户型不方正,会让你越住越穷?
  • 实用指南:Stable Diffusion 短视频制作算力需求与优化策略研究
  • 如何高效地学习Java编程?
  • 实用指南:【底层机制】深入浅出地、系统地剖析 Appium 的原理
  • 容错量子电路大幅降低资源开销
  • 详细介绍:【C基本功】类型转换的奇幻漂流
  • 点灯笔记:CW32L010
  • 过山车
  • day07 spark sql - 详解
  • 深入解析:系统架构设计师备考第57天——云原生架构相关技术
  • 【ArcMap】将一个线图层的属性字段连接到另一个线图层
  • 人工智能之数据分析 numpy:第十四章 知识总结
  • 信息的建筑学:MyBatis Log Panda 如何重构开发者的认知地图
  • ai论文软件推荐:智能工具助力学术写作效率提升
  • 2025年11月软瓷厂家推荐榜:3D软瓷/软瓷砖/mcm软瓷/3D打印软瓷厂家批发环保品质深度解析!
  • 降ai率免费网站:助力内容原创性提升的实用工具
  • PVC地板厂家天津航美国际贸易有限公司:华北平价基地核心成员,规模化降本,耐磨防滑产品适配多场景
  • PVC地板厂家天津航美:2016年成立深耕行业,同质透心/地板革等全品类,防火阻燃符合国际标准
  • 云拨测:当“正常变更”摧毁全球网络时,谁来守护你的业务可用性?