2020牛客暑期多校训练营(第八场)Enigmatic Partition
题目链接
https://ac.nowcoder.com/acm/contest/5673/E
题目大意
将数 x 拆分,需要满足拆分的数的最大和最小的差值为2,且相邻两个数的差值不能超过1
定义 f(x) 为满足条件的拆分的方案数 , 求
解题思路
打个表可以发现以 L 为最小值 , len 为长度的拆分方案数是以一定规律变化的
(从某个数开始每隔两项满足条件的方案数+1,从某个数开始每隔两项满足条件的方案数-1)
我们可以枚举 L 和 len , 然后每次达到某个点的时候开始更新方案数
这个操作可以用差分去维护区间的增值和减值
但每次更新需要从当前项不断向后移动两格直到边界 , 时间复杂度很显然是不行的
那怎么办呢?
当然是差分套差分啦( 也就是二阶差分 )
用第一阶差分维护第二阶差分所要维护的区间的增值和减值就OK了
AC_Code
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 1e5 + 10 , M = 1e6 + 10; int add[M] , f[N]; void init() { int up = N - 10; for(int l = 1 ; l <= up ; l ++) for(int len = 3 ; len * l <= up ; len ++) { add[l * len + 3] ++ , add[(l + 1) * len + 1] -- ; add[(l + 1) * len + 2] -- , add[(l + 2) * len - 3 + 3] ++ ; } for(int i = 3 ; i <= up ; i ++) add[i] += add[i - 2]; for(int i = 1 ; i <= up ; i ++) add[i] += add[i - 1]; for(int i = 1 ; i <= up ; i ++) f[i] = f[i - 1] + add[i]; } signed main() { ios::sync_with_stdio(false); cin.tie(0) , cout.tie(0); init(); int T = 1; cin >> T; for(int k = 1 ; k <= T ; k ++) { int l , r; cin >> l >> r; cout << "Case #" << k << ": "; cout << f[r] - f[l - 1] << '\n'; } return 0; }
凡所不能将我击倒的,都将使我更加强大
本文作者:GsjzTle
本文链接:https://www.cnblogs.com/GsjzTle/p/13437401.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 依赖注入中的 Captive Dependency
· .NET Core 对象分配(Alloc)底层原理浅谈
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
· 为什么 .NET8线程池 容易引发线程饥饿
· 终于决定:把自己家的能源管理系统开源了!
· [.NET] 使用客户端缓存提高API性能
· 外部H5唤起常用小程序链接规则整理
· C#实现 Winform 程序在系统托盘显示图标 & 开机自启动
· WPF 怎么利用behavior优雅的给一个Datagrid添加一个全选的功能