Description
Input
Output
Sample Input
3
3 5 1 2 2 3
1 2
0 2
2 2
1 1 2
1 1 3
0 2 3 7
0 3 2 9
1 1 3
Sample Output
499122179
748683273
966554063
Data Constraint
Hint
以下为样例解释:
分析:
基础分的期望非常显然,即
Basicscore=A∗∑i=lrpiBasicscore=A∗∑i=lrpi
设fifi为combo(i)combo(i)的期望,连击分期望就是
Comboscore=B∗∑i=lrpi∗(fi−1+1)Comboscore=B∗∑i=lrpi∗(fi−1+1)
显然这次要是11才能得到分,分数值显然就是i−1i−1的期望+1+1了。
考虑怎样求fifi,显然可以从i−1i−1转移,考虑当前为是否为11,有
tt就是题目中的那个,就等于tatbtatb。
化简上面的式子,得
fi=(pi+t−pi∗t)fi−1+pifi=(pi+t−pi∗t)fi−1+pi
显然是一个关于fi−1fi−1的一次函数,那么ComboscoreComboscore也是一个一次函数。
我们考虑线段树维护区间[L,R][L,R]的55个值,分别为,表示概率和(解决基本分),fR=k∗fL−1+bfR=k∗fL−1+b,Comboscore(l,r)=sumk∗fL−1+sumbComboscore(l,r)=sumk∗fL−1+sumb。
考虑合并两个区间,因为右区间的fL−1fL−1就是左区间的fRfR,这就是我们维护这两个东西的原因。具体转移可以手推,程序也有。
程序常数较大,最后我全部intint加强制类型转换卡过去了。
(我的程序就算慢得爆炸,常数大得飞起,也不会开读入优化)
代码:
#include <iostream>
#include <cmath>
#include <cstdio>
#define LL long long
const int maxn=5e5+7;
const LL mod=998244353;
using namespace std;
int n,test,op,l,r;
int A,B,T,ta,tb,x,y;
int pi[maxn];
struct node{
int sump,k,b,sumk,sumb;
}t[maxn*4];
int power(int x,int y)
{
if (y==1) return x;
int c=power(x,y/2);
c=(LL)c*(LL)c%mod;
if (y%2) c=(LL)c*(LL)x%mod;
return c;
}
node neww(int p)
{
node z;
z.sump=p;
z.k=((LL)p+(LL)T+mod-(LL)p*(LL)T%mod)%mod;
z.b=p;
z.sumk=p;
z.sumb=p;
return z;
}
node merge(node x,node y)
{
node z;
z.sump=((LL)x.sump+(LL)y.sump)%mod;
z.k=((LL)x.k*(LL)y.k)%mod;
z.b=((LL)y.k*(LL)x.b%mod+(LL)y.b)%mod;
z.sumk=((LL)y.sumk*(LL)x.k%mod+(LL)x.sumk)%mod;
z.sumb=((LL)y.sumk*(LL)x.b%mod+(LL)x.sumb+(LL)y.sumb)%mod;
return z;
}
void build(int p,int l,int r)
{
if (l==r)
{
t[p]=neww(pi[l]);
return;
}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p]=merge(t[p*2],t[p*2+1]);
}
void change(int p,int l,int r,int x,LL k)
{
if (l==r)
{
t[p]=neww(k);
return;
}
int mid=(l+r)/2;
if (x<=mid) change(p*2,l,mid,x,k);
else change(p*2+1,mid+1,r,x,k);
t[p]=merge(t[p*2],t[p*2+1]);
}
node query(int p,int l,int r,int x,int y)
{
if ((l==x) && (r==y)) return t[p];
int mid=(l+r)/2;
if (y<=mid) return query(p*2,l,mid,x,y);
else if (x>mid) return query(p*2+1,mid+1,r,x,y);
else
{
return merge(query(p*2,l,mid,x,mid),query(p*2+1,mid+1,r,mid+1,y));
}
}
int main()
{
freopen("omeed.in","r",stdin);
freopen("omeed.out","w",stdout);
scanf("%d",&n);
scanf("%d%d%d%d%d%d",&n,&test,&ta,&tb,&A,&B);
T=(LL)ta*(LL)power(tb,mod-2)%mod;
for (int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
pi[i]=(LL)x*(LL)power(y,mod-2)%mod;
}
build(1,1,n);
for (int i=1;i<=test;i++)
{
scanf("%d",&op);
if (op==0)
{
scanf("%d%d%d",&l,&x,&y);
LL p=(LL)x*(LL)power(y,mod-2)%mod;
change(1,1,n,l,p);
}
else
{
scanf("%d%d",&l,&r);
node d=query(1,1,n,l,r);
LL ans=((LL)A*(LL)d.sump%mod+(LL)B*(LL)d.sumb%mod)%mod;
printf("%lld\n",ans);
}
}
}