Luogu P3600 随机数生成器

题目描述

sol研发了一个神奇的随机数系统,可以自动按照环境噪音生成真·随机数。

现在sol打算生成\(n\)个\([1,x]\)的整数\(a_1...a_n\),然后进行一些询问。

\(q\)次询问,每次询问i有两个参数\(li\)和\(ri\),sol会计算\(\min_{li \leq j \leq ri} a_j\)(a数组中下标在\(li、ri\)之间的数的最小值)。

最后测试结果会是这些询问得到的结果的最大值。

sol进行了很多次实验,现在他想问问你测试结果的期望大小是多少,对\(666623333\)取模。

输入输出格式

输入格式:

第一行三个数\(n、x、q\)。

下面q行,第i行两个数表示\(li\)和\(ri\)。

输出格式:

一行一个数,表示答案。

输入输出样例

输入样例#1:

2 2 1
1 2

输出样例#1:

499967501

输入样例#2:

6 6 6
1 3
2 4
3 5
4 6
5 6
3 4

输出样例#2:

88571635

根据整数期望公式:

\[\begin{align}
ans&=\sum_{i=1}^xi*p(X=i)\\
&=\sum_{i=1}^xp(X\geq i)\\
&=\sum_{i=1}^x1-p(X<i)
\end{align}
\]

因为是所有的最小值取最大值,所以\(p(X<i)\)比\(p(X\geq i)\)好求一些。

我们考虑对每个\(i\)分别求。

合法情况要求询问的每个区间中至少有一个\(<i\)的数。如果两个区间有包含关系,很明显大的区间没有用。将剩余的区间按左端点排序后,对于坐标上的每个点,包含它的区间的编号一定是连续的。所以我们将问题转换:有很多区间,选择一个区间的概率为\(P\),要选择一些区间将整个坐标轴覆盖,问概率。

很明显这些区间的左右端点都是单调不下降的(去掉无用区间)。设\(f_i\)表示最后一个选择的区间为\(i\),并且将\(r_i\)以及之前的坐标都覆盖了的概率。

\[f_i=\sum_{r_j\geq l_i-1}f_j*P*(1-P)^{i-j-1}
\]

前缀和优化一下单次\(DP\)就可以做到\(O(n)\)了。

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 2005 using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} const ll mod=666623333;
ll ksm(ll t,ll x) {
ll ans=1;
for(;x;x>>=1,t=t*t%mod)
if(x&1) ans=ans*t%mod;
return ans;
} int n,x,m;
struct interval {
int l,r;
bool operator <(const interval &a)const {
if(l!=a.l) return l<a.l;
return r>a.r;
}
}s[N]; interval st[N];
int top; int L[N],R[N];
ll ans;
ll DP(ll p) {
if(p==1) return 1;
static ll f[N],pw[N],inv[N];
memset(f,0,sizeof(f)); pw[0]=inv[0]=1;
for(int i=1;i<=n;i++) pw[i]=pw[i-1]*(mod+1-p)%mod;
inv[1]=ksm(mod+1-p,mod-2);
for(int i=2;i<=n;i++) inv[i]=inv[i-1]*inv[1]%mod;
f[0]=1;
int lx=0,rx=0;
ll sum=1;
for(int i=1;i<=n;i++) {
while(lx<=i&&R[lx]<L[i]-1) {
sum=(sum-f[lx]*inv[lx]%mod+mod)%mod;
lx++;
}
while(rx+1<i&&R[rx+1]>=L[i]-1) {
sum=(sum+f[rx+1]*inv[rx+1])%mod;
rx++;
}
f[i]=sum*p%mod*pw[i-1]%mod;
}
ll ans=0;
for(int i=1;i<=n;i++) {
if(R[i]==m) (ans+=f[i]*pw[n-i])%=mod;
}
return ans;
} int main() {
n=Get(),x=Get(),m=Get();
for(int i=1;i<=m;i++) s[i].l=Get(),s[i].r=Get();
sort(s+1,s+1+m);
for(int i=1;i<=m;i++) {
while(top>=1&&st[top].r>=s[i].r) top--;
st[++top]=s[i];
} m=top;
for(int i=1;i<=m;i++) s[i]=st[i]; for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) if(s[j].l<=i&&i<=s[j].r) R[i]=j;
for(int j=m;j>=1;j--) if(s[j].l<=i&&i<=s[j].r) L[i]=j;
}
top=0;
for(int i=1;i<=n;i++) {
if(L[i]&&R[i]) L[++top]=L[i],R[top]=R[i];
}
n=top;
ll invx=ksm(x,mod-2);
for(int i=1;i<=x;i++) {
(ans+=mod+1-DP((i-1)*invx%mod))%=mod;
}
cout<<ans;
return 0;
}

Luogu P3600 随机数生成器的更多相关文章

  1. Luogu P3600 随机数生成器(期望+dp)

    题意 有一个长度为 \(n\) 的整数列 \(a_1, a_2, \cdots, a_n\) ,每个元素在 \([1, x]\) 中的整数中均匀随机生成. 有 \(q\) 个询问,第 \(i\) 个询 ...

  2. luogu P3600 随机数生成器【dp】

    把期望改成方案数最后除一下,设h[i]为最大值恰好是i的方案数,那么要求的就是Σh[i]*i 首先包含其他区间的区间是没有意义的,用单调栈去掉 然后恰好不好求,就改成h[i]表示最大值最大是i的方案数 ...

  3. 洛谷P3600 随机数生成器(期望dp 组合数)

    题意 题目链接 Sol 一条重要的性质:如果某个区间覆盖了另一个区间,那么该区间是没有用的(不会对最大值做出贡献) 首先不难想到枚举最终的答案\(x\).这时我们需要计算的是最大值恰好为\(x\)的概 ...

  4. P3600 随机数生成器

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  5. 洛谷P3600随机数生成器——期望+DP

    原题链接 写到一半发现写不下去了... 所以orz xyz32768,您去看这篇题解吧,思路很清晰,我之前写的胡言乱语与之差距不啻天渊 #include <algorithm> #incl ...

  6. 洛谷 P3600 - 随机数生成器(期望 dp)

    题面传送门 我竟然独立搞出了这道黑题!incredible! u1s1 这题是我做题时间跨度最大的题之一-- 首先讲下我四个月前想出来的 \(n^2\log n\) 的做法吧. 记 \(f(a)=\m ...

  7. luogu P2354 [NOI2014]随机数生成器 贪心 卡空间 暴力

    LINK:随机数生成器 观察数据范围还是可以把矩阵给生成出来的. 考虑如何求出答案.题目要求把选出的数字从小到大排序后字典序尽可能的小 实际上这个类似于Mex的问题. 所以要从大到小选数字 考虑选择一 ...

  8. 【原创】开源Math.NET基础数学类库使用(13)C#实现其他随机数生成器

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  9. 【BZOJ-3122】随机数生成器 BSGS

    3122: [Sdoi2013]随机数生成器 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1362  Solved: 531[Submit][Sta ...

随机推荐

  1. Violet音乐社区 - 个人总结报告

    一.项目概述 1.1 项目背景 音乐是一门艺术,是由有组织的乐音来表达人们情感.反映人类现实生活情感的艺术.现代科技的发展使得人们可以利用网络随时随地的享受音乐,然而在当今互联网却很少有一个以音乐为媒 ...

  2. LuaSocket 学习笔记

    --- LUA SocketLib 和 协程 前言: 这是一篇译文(The LUA SocketLib and the Coroutines),有删改,原文见下方链接. 简介 目标读者:会使用 LUA ...

  3. python实现fibonacci数列的三种方法

    第一种:递归法 def fibo(n): if n < 3: return 1 return fibo(n-1) + fibo(n-2) print(fibo(6)) 第二种:循环 def fi ...

  4. 十一、Powell算法(鲍威尔算法)原理以及实现

    一.介绍 Powell算法是图像配准里面的常用的加速算法,可以加快搜索速度,而且对于低维函数的效果很好,所以本篇博客主要是为了介绍Powell算法的原理以及实现. 由于网上已经有了对于Powell算法 ...

  5. linux常用命令总结篇

    关于linux的一些基础命令,以前也学过,但是长时间不用还是感觉生疏了,所以记录下来以便后期温故知新. 1. cd:cd命令用来切换工作目录至dirname.cd ~ 进入用户主目录,cd - 进入之 ...

  6. 《Netty Redis Zookeeper 高并发实战》声明

    疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 这里, 对疯狂创客圈 <Netty Redis Zookeeper 高并发实战> 一书,进行一些必要说明. ...

  7. PHP 将内容写入word pdf 换行符不生效咋办

    答:把单引号换成双引号就能解析换行符(\n)了,

  8. 你可能会忽略的 Git 提交规范

    一.为什么需要规范? 无规矩不成方圆,编程也一样. 如果你有一个项目,从始至终都是自己写,那么你想怎么写都可以,没有人可以干预你.可是如果在团队协作中,大家都张扬个性,那么代码将会是一团糟,好好的项目 ...

  9. Elasticsearch 6.x版本全文检索学习之集群调优建议

    1.系统设置要到位,遵照官方建议设置所有的系统参数. https://www.elastic.co/guide/en/elasticsearch/reference/6.7/setup.html 部署 ...

  10. 个人项目开源之c++基于epoll实现高并发游戏盒子(服务端+客户端)源代码

    正在陆续开源自己的一些项目 此为c++实现高并发的游戏盒子,平台问题需要迁移重构,所以有一些遗留问题,客户端异常断开没有处理,会导致服务器崩溃,还有基于快写代码编程平台实现的小程序切换,线程读写缓存没 ...