牛客 2018NOIP 模你赛2 T2 分糖果 解题报告
分糖果
链接:https://www.nowcoder.com/acm/contest/173/B
来源:牛客网
题目描述
\(N\) 个小朋友围成一圈,你有无穷个糖果,想把其中一些分给他们。
从某个小朋友开始,我们顺时针给他们标号为\(1\) ~ \(N\)。第 \(i\) 个小朋友可以得到至多 \(a[i]\),至少 \(1\) 个糖果。
问,有多少种分配方案使得每一对相邻的小朋友拿到的糖果数不同。答案对 \(10^9 + 7\) 取模。
输入描述:
第一行一个整数 \(N\)。
接下来一行 \(N\) 个整数,第 \(i\) 个数表示 \(a[i]\)。
输出描述:
一行一个整数,表示答案。
说明:
对全部的测试数据,\(n <= 10^6, a_i <= 10^9\)
- \(10\) 分的数据,\(n <= 4\)
- \(10\) 分的数据,\(n <= 100,a_i <= 20\)
- \(20\) 分的数据,\(n <= 100,a_i <= 100\)
- \(10\) 分的数据,\(n <= 10^5,a_i\) 全部相等
- \(30\) 分的数据,\(n <= 10^5,a_i\) 为随机生成
- \(20\) 分的数据,\(n <= 10^6\).
UPDATA:10.16 发现自己的想法可能很不优美,可能回来更改。
当时讲得视频本蒟蒻死活听不懂,回来花了好几天的语文课总算是能够自己理解了,和视频里面讲得并不太一样,也许是我理解麻烦了说不定
40pts的普通区间DP就不说了,不过吐槽一下没有\(N^2\)的档,事实上不用容斥是可以做到\(N^2\)的,只需要一些断环的技巧
下面正题
- 大致分为三个步骤:
1 链上答案的统计
2 化链为环
3 单调栈优化
现在仅考虑为链的情况
先回归一下问题的本质,我们可以这样描述这个问题,我们要填满一个长度为\(n\)的数组,要求每两个相邻的位置填的数不能相等,每个位置\(i\)的可填集合为\(1\)-\(a_i\)的整数。(这看起来有变吗??
行吧,根据正难则反,换成容斥的话,先不管条件,求总方案,然后按照填了几个相等的数作为容斥系数,直接统计?听起来好像非常有道理,然而一点也说不到重点
这里直接给出状态转移方程进行分析了(事实上文字描述说起来不清楚,还容易产生误导
\(dp_i\)表示前\(i\)个位置构成的合法的方案数
\(dp_i=\sum_{i=0}^{i-1} dp_j \times min_{k=j+1}^i a_k \times (-1)^{i-j-1}\)
\(dp_0=1\)
从\(i-1\)位置的转移开始理解
我们在\(i\)位置上对前面所有的情况填取\(a_i\)中可能
产生的不合法情况只有\(i\)与\(i-1\)位置相等的一些情况,我们需要减去它们
那我们不妨把这两个状态相等的情况通过\(dp_{i-2}\)递推过来,但这样我们就多减去了后三个相等的情况,就是容斥了
于是,我们就得到了一个优秀的在链上的\(O(N^2)\)算法了
怎么搞到环上?减去第一段和最后一段相等的情况。
为了方便,让第一段为最小的元素,这样可以用\(a_1\)统计方案了
这里我没有用到特别容斥的方案来理解(事实上感觉也是
首先,长度为2的链直接就是一个环了
长度为3的链减去长度为2的环就可以拼成环了
原理是对第三个位置填上和第一个位置相等的元素,每种情况只能填一个,\(a_1\)最小保证一定有的填
类推 长度为\(n\)的链减去一个长度为\(n-1\)的环可以拼成一个长为\(n\)的环
好啦,于是得到了一个优秀的\(O(N^2)\)完整版
事实上第三部分的思维难度最低(但是写起来恶心啊
转移方程有
\(dp_i=\sum_{i=0}^{i-1} dp_j \times min_{k=j+1}^i a_k \times (-1)^{i-j-1}\)
化简一下
\(dp_i=(-1)^{i} \times \sum_{i=0}^{i-1} dp_j \times min_{k=j+1}^i a_k \times (-1)^{j+1}\)
发现后面很多段\(dp_i\)乘的都是一个\(a_k\),而且\(a_k\)是按位置递增的
单调栈了
实现细节因人而异,不多说了
Code:
#include <cstdio>
#define ll long long
const int N=1e6+10;
const int inf=0x7fffffff;
const ll mod=1e9+7;
int n,a[N],b[N],mi=inf,id,s[N],tot;
ll dp[N],ans,f[N],sum;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",b+i);
if(b[i]<mi)
mi=b[i],id=i;
}
int cnt=0;
while(cnt<n)
{
a[++cnt]=b[id++];
id==n+1&&(id=1);
}
f[0]=1,f[1]=1-a[1],sum=a[1],dp[1]=a[1],s[++tot]=1;
for(int las,i=2;i<=n;i++)
{
while(tot&&a[s[tot]]>=a[i])
(sum-=a[s[tot]]*(f[s[tot]-1]-(tot-1?f[s[tot-1]-1]:0)))%=mod,--tot;
(sum+=a[i]*(f[i-1]-(tot?f[s[tot]-1]:0)))%=mod;
dp[i]=sum*(i&1?1:-1);
(f[i]=f[i-1]+dp[i]*(i&1?-1:1))%=mod;
s[++tot]=i;
}
for(int i=n;i>1;i--)
(ans+=dp[i]*(n-i&1?-1:1))%=mod;
printf("%lld\n",(ans+mod)%mod);
return 0;
}
2018.9.21
牛客 2018NOIP 模你赛2 T2 分糖果 解题报告的更多相关文章
- 牛客NOIP暑期七天营-普及组1 解题报告
A 对于\(100\%\),直接开个桶统计即可.入门题目. 代码:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=41 ...
- 牛客NOIP暑期七天营-提高组1 解题报告
https://ac.nowcoder.com/acm/contest/920#question A 构造+双指针 发现m的限制是1e5,而点数是5e4,所以不能构造太多的边,思考一下最短路树的定义. ...
- 【牛客OI赛制测试赛3】 毒瘤xor
牛客OI赛制测试赛3 毒瘤xor 传送门 题面,水表者自重 Solution 前缀和简单题(挖坑待补) 代码实现 #include<stdio.h> #define int long lo ...
- 牛客OI赛制测试赛2(0906)
牛客OI赛制测试赛2(0906) A :无序组数 题目描述 给出一个二元组(A,B) 求出无序二元组(a,b) 使得(a|A,b|B)的组数 无序意思就是(a,b)和(b,a) 算一组. 输入描述: ...
- 牛客网多校赛第9场 E-Music Game【概率期望】【逆元】
链接:https://www.nowcoder.com/acm/contest/147/E 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...
- 8.30 牛客OI赛制测试赛1 F题 子序列
题目描述 给出一个长度为n的序列,你需要计算出所有长度为k的子序列中,除最大最小数之外所有数的乘积相乘的结果 输入描述: 第一行一个整数T,表示数据组数.对于每组数据,第一行两个整数N,k,含义如题所 ...
- 牛客OI赛制测试赛2
A题: https://www.nowcoder.com/acm/contest/185/A 链接:https://www.nowcoder.com/acm/contest/185/A来源:牛客网 题 ...
- 牛客网-湘潭大学校赛重现H题 (线段树 染色问题)
链接:https://www.nowcoder.com/acm/contest/105/H来源:牛客网 n个桶按顺序排列,我们用1~n给桶标号.有两种操作: 1 l r c 区间[l,r]中的每个桶中 ...
- 牛客网多校赛第九场A-circulant matrix【数论】
链接:https://www.nowcoder.com/acm/contest/147/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...
随机推荐
- 第34-1题:LeetCode112. Path Sum I
题目 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和. 说明: 叶子节点是指没有子节点的节点. 示例: 给定如下二叉树,以及目标和 sum ...
- OA上传和编辑数据
1.VO:value object值对象.通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已.但应是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要. 2. String[]类型打 ...
- Linux实战教学笔记05:远程SSH连接服务与基本排错
第1章 远程连接LInux系统管理 1.1 为什么要远程连接Linux系统 在实际的工作场景中,虚拟机界面或物理服务器本地的窗口都是很少能够接触到的,因为服务器装完系统后,都要拉到IDC机房托管,如果 ...
- asp.net高并发网站解决方案【未完成版本】
场景:假设现在是一个电商网站,今天要举办活动,有10个商品低价销售,但是会来抢购的人会特别多,最后只有十个人可以成功的买到商品 明确2个问题 1.访问量:抢票时间断用户访问量 2.并发:1秒内请求 ...
- PHP无限分类生成树方法,非递归,引用
//这个是核心方法 function generateTree($items){ $tree = array(); foreach($items as $item){ ...
- Python学习笔记:单例模式
单例模式:一个类无论实例化多少次,返回的都是同一个实例,例如:a1=A(), a2=A(), a3=A(),a1.a2和a3其实都是同一个对象,即print(a1 is a2)和print(a2 is ...
- python系列2之数据类型
目录 Python数据类型 python的运算符 Python的循环与判断语句 python练习 Python作业 一. Python的数据类型 1. 整型(int) <1>. 赋值 ...
- OC中block作方法参数时的用法
方式一.在传参时直接声明block回调方法. 1. 定义方法: - (int)doTest:(NSString *)name para1:(int)temp1 para2:(int)temp2 suc ...
- [CodeForces950C]Zebras
Description 题目地址: Codeforces 题意:给你一串只含01的字符串,判断能否将字符串分为k个子序列,使得子序列满足以下条件: 开头和结尾都是0 相邻的2个数是01或者10 如0, ...
- 17-比赛1 A - Weak in the Middle (栈)
题目描述 给定长度为 N 的序列 A.每天,序列 A 中所有比两侧元素都小的元素都会消失.对于原序列中所有元素,请求出它会在第几天之后消失(天数从 1 开始计算),或者指出它不会消失. 数据范围 1 ...