2020-08-05 02:55阅读: 196评论: 0推荐: 0

2020牛客暑期多校训练营(第八场)Enigmatic Partition

题目链接

https://ac.nowcoder.com/acm/contest/5673/E

题目大意

将数 x 拆分,需要满足拆分的数的最大和最小的差值为2,且相邻两个数的差值不能超过1

定义 f(x) 为满足条件的拆分的方案数 , 求 i=LRf(i)

解题思路 

参考博客

打个表可以发现以 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 中国大陆许可协议进行许可。

posted @   GsjzTle  阅读(196)  评论(0编辑  收藏  举报
编辑推荐:
· .NET 依赖注入中的 Captive Dependency
· .NET Core 对象分配(Alloc)底层原理浅谈
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
· 为什么 .NET8线程池 容易引发线程饥饿
阅读排行:
· 终于决定:把自己家的能源管理系统开源了!
· [.NET] 使用客户端缓存提高API性能
· 外部H5唤起常用小程序链接规则整理
· C#实现 Winform 程序在系统托盘显示图标 & 开机自启动
· WPF 怎么利用behavior优雅的给一个Datagrid添加一个全选的功能
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 アゲイン 横山克
  2. 2 私の嘘 横山克
アゲイン - 横山克
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.