Problem
整数期望公式
E
(
x
)
=
∑
i
∞
P
(
x
≥
i
)
E(x)=\sum_i^∞ P(x\geq i)
E(x)=∑i∞P(x≥i)
这个和我们常用的
E
(
x
)
=
∑
i
∞
P
(
i
)
∗
i
E(x)=\sum_i^∞ P(i)*i
E(x)=∑i∞P(i)∗i其实是等价的,因为
P
(
x
≥
i
)
=
∑
j
=
i
∞
P
(
j
)
P(x\geq i)=\sum_{j=i}^∞ P(j)
P(x≥i)=∑j=i∞P(j),这就相当于把原来的
P
(
i
)
∗
i
P(i)*i
P(i)∗i拆成i份,加到前面的P之中。
Solution
E
(
a
n
s
)
=
∑
i
=
1
x
1
−
P
(
a
n
s
<
i
)
E(ans)=\sum_{i=1}^x 1-P(ans<i)
E(ans)=∑i=1x1−P(ans<i)。
显然对于一个询问区间包含另一个询问区间的情况下,前者是可以直接舍弃的,因为前者的
min
≤
\min\leq
min≤后者的
min
\min
min。
为了避免重叠区间的相互影响,我们对序列中的元素进行考虑。那么可以预处理出覆盖到点i的询问,显然它应该是一段连续的区间,记为
[
p
r
e
[
i
]
,
n
x
t
[
i
]
]
[pre[i],nxt[i]]
[pre[i],nxt[i]]。而第i个点有
i
−
1
x
\frac {i-1} x
xi−1的概率会小于i,对覆盖到它的区间做贡献,使得这些区间满足条件。
不妨设 f [ i ] f[i] f[i]表示位置i做贡献且1~pre[i]-1的询问全都已经满足条件的概率。枚举上一个做贡献的点,则有方程
f [ i ] = p ∗ ( [ p r e [ i ] = = 1 ] ∗ ( 1 − p ) i − 1 + ∑ n x t [ j ] ≥ p r e [ i ] − 1 f [ j ] ∗ ( 1 − p ) i − j − 1 ) f[i]=p*([pre[i]==1]*(1-p)^{i-1}+\sum_{nxt[j]\geq pre[i]-1} f[j]*(1-p)^{i-j-1}) f[i]=p∗([pre[i]==1]∗(1−p)i−1+nxt[j]≥pre[i]−1∑f[j]∗(1−p)i−j−1)
最后的答案就是 ∑ n x t [ i ] = q f [ i ] ∗ ( 1 − p ) n − i \sum_{nxt[i]=q} f[i]*(1-p)^{n-i} ∑nxt[i]=qf[i]∗(1−p)n−i
由于区间的
l
l
l和
r
r
r都分别是递增的,
t
w
o
−
p
o
i
n
t
e
r
two-pointer
two−pointer一下即可做到
O
(
n
)
O(n)
O(n)的DP了。
时间复杂度
O
(
n
x
)
O(nx)
O(nx)
好像设 f [ i ] f[i] f[i]表示右端点小于等于 i i i的区间均满足条件也可以做,但是我不会转移= =||
Code
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=2010,mod=666623333;
struct data{
int l,r;
bool operator < (const data &x)const
{
if(l==x.l) return r>x.r;
return l<x.l;
}
}a[maxn];
struct Stack{
int tp,a[maxn];
Stack(){tp=0;}
void push(int val){a[++tp]=val;}
int top(){return a[tp];}
void pop(){tp--;}
}stk;
int n,x,q,p,pc,ans,pre[maxn],nxt[maxn],inv[maxn],f[maxn];
int power(int x,int y)
{
int res=1;
while(y)
{
if(y&1) res=(ll)res*x%mod;
x=(ll)x*x%mod;y>>=1;
}
return res;
}
void input()
{
int head=1,tail=0;
scanf("%d%d%d",&n,&x,&q);
for(int i=1;i<=q;i++) scanf("%d%d",&a[i].l,&a[i].r);
sort(a+1,a+q+1);
for(int i=1;i<=q;i++)
{
while(a[i].r<=a[stk.top()].r) stk.pop();
stk.push(i);
}
q=stk.tp;
for(int i=1;i<=q;i++) a[i]=a[stk.a[i]];
for(int i=1;i<=n;i++)
{
while(tail<q&&a[tail+1].l<=i) tail++;
while(head<=tail&&a[head].r<i) head++;
pre[i]=head;nxt[i]=tail;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
input();
for(int i=1;i<=x;i++)
{
int j=0,s=1,t=1;
inv[0]=1;f[0]=1;
p=((ll)(i-1+mod)%mod*power(x,mod-2))%mod;
pc=(1-p+mod)%mod;inv[1]=power(pc,mod-2);
for(int k=2;k<=n;k++) inv[k]=(ll)inv[k-1]*inv[1]%mod;
for(int k=1;k<=n;k++)
{
while(j<k&&nxt[j]<pre[k]-1)
s=(s-((ll)f[j]*inv[j]%mod)+mod)%mod,j++;
f[k]=(ll)s*t%mod*p%mod;t=(ll)t*pc%mod;
s=(s+(ll)f[k]*inv[k])%mod;
}
s=0;t=1;
for(int k=n;k>=1&&nxt[k]==q;k--)
s=(s+(ll)f[k]*t%mod)%mod,t=(ll)t*pc%mod;
ans+=(1-s+mod)%mod;
if(ans>=mod) ans-=mod;
}
printf("%d\n",ans);
return 0;
}