[cf 1264 C] Beautiful Mirrors with queries

题意:

你有$n$个魔镜,第$i$个魔镜有$p_{i}$的概率说你美。

从第1天开始,你会依次询问魔镜$1-n$你美不美。

若第$i$个魔镜说你美则你明天会继续询问第$i+1$个魔镜。

否则你明天会从该魔镜前面第一个复活点魔镜开始询问。初始时只有魔镜1是复活点。

当第$n$个魔镜说你美的时候你会开心的一批。

现在有$q$次操作,每次操作修改一个魔镜使其成为/不成为复活点。

每次操作之后请你求出期望多少天你能开心的一批。

$n,q\leq 2\times 10^{5}$。

题解:

一开始想复杂了,用期望的线性性推了个式子发现做不了。

实际上我们只需要根据最简单的思路推式子即可。

设$E_{i}$为从$i$走到$n$的期望天数。

则有$E_{i}=p_{i}\times(1+E_{i+1})+(1-p_{i})\times(1+E_{1})$。

手动消元一下$E_{1}$,得到$E_{1}=\frac{1}{p_{n}}+\frac{1}{p_{n}p_{n-1}}+\cdots +\frac{1}{p_{n}p_{n-1}\cdots p_{1}}$。

那么考虑复活点这件事,容易发现整个序列被复活点分成了若干个区间。

每个区间是独立的。即$ans=\sum{E_{[f_{i-1},f_{i}]}}$。

那么我们考虑$E_{[l,r]}$如何计算。

推广上面那个式子,得到$E_{[l,r]}=\frac{1}{p_{r}}+\frac{1}{p_{r}p_{r-1}}+\cdots +\frac{1}{p_{r}p_{r-1}\cdots p_{l}}$。

我们设$s_{i}$为$p_{1}p_{2}\cdots p_{i}$,那么有

$E_{[l,r]}=\frac{(p_{r-1}p_{r-2}\cdots p_{l}+p_{r-2}p_{r-3}\cdots p_{l}+\cdots +p_{l}+1)}{\frac{s_{r}}{s_{l-1}}}$。

我们再设$ss_{i}=s_{1}+s_{2}+\cdots +s_{i}$,那么有

$E_{[l,r]}=\frac{\frac{(ss_{r-1}-ss_{l-1})}{s_{l-1}}+1}{\frac{s_{r}}{s_{l-1}}}$。

于是只需要用一个$set$维护复活点即可做到$O(nlogn)$。

代码:

#include<bits/stdc++.h>
#define maxn 200005
#define maxm 500005
#define inf 0x7fffffff
#define mod 998244353
#define ll long long
#define debug(x) cerr<<#x<<": "<<x<<endl
#define fgx cerr<<"--------------"<<endl
#define dgx cerr<<"=============="<<endl

using namespace std;
ll s[maxn],ss[maxn];
set<int> st;

inline ll read(){
    ll x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}

inline ll power(ll a,ll b){ll ans=1;while(b) ans=(b&1)?ans*a%mod:ans,a=a*a%mod,b>>=1;return ans;}
inline ll inv(ll x){return power(x,mod-2);}
inline ll mo(ll x){return x>=mod?x-mod:x;}
inline ll calc(ll l,ll r){return (mo(ss[r-1]-ss[l-1]+mod)*inv(s[l-1])%mod+1)*inv(s[r]*inv(s[l-1])%mod)%mod;}

int main(){
    ll n=read(),q=read(); s[0]=1;
    for(ll i=1;i<=n;i++){
        ll x=read()*inv(100)%mod;
        s[i]=s[i-1]*x%mod,ss[i]=(ss[i-1]+s[i])%mod;
    }
    st.insert(1),st.insert(n+1);
    ll ans=(ss[n-1]+1)%mod*inv(s[n])%mod;
    while(q--){
        int x=read();
        set<int>::iterator it=st.lower_bound(x);
        if(*it==x){
            int l=*(--it);it++;int r=(*(++it));//cout<<1<<":"<<l<<" "<<r<<endl;
            ans=mo(ans-calc(l,x-1)+mod),ans=mo(ans-calc(x,r-1)+mod),ans=mo(ans+calc(l,r-1)),st.erase(x);
        }
        else{
            int l=*(--it);it++;int r=(*it);//cout<<2<<":"<<l<<" "<<r<<endl;
            ans=mo(ans-calc(l,r-1)+mod),ans=mo(ans+calc(l,x-1)),ans=mo(ans+calc(x,r-1)),st.insert(x);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

C

原文地址:https://www.cnblogs.com/YSFAC/p/12003135.html

时间: 2024-08-08 07:41:12

[cf 1264 C] Beautiful Mirrors with queries的相关文章

Codeforces - 1264C - Beautiful Mirrors with queries - 概率期望dp

一道挺难的概率期望dp,花了很长时间才学会div2的E怎么做,但这道题是另一种设法. https://codeforces.com/contest/1264/problem/C 要设为 \(dp_i\) 表示第 \(i\) 个格子期望经过多少次,所以 \(dp_{n+1}=1\). https://www.cnblogs.com/suncongbo/p/11996219.html 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12063633.ht

cf B Very Beautiful Number

题意:给你两个数p和x,然后让你找出一个长度为p的数,把它的最后移到最前面之后得到的数是原来数字的x倍,有很多这样的数取最小. 思路:枚举最后一位,然后就可以推出整个的一个数,然后比较得到的数的第一个数字和枚举的数字是否相等既可以. 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 7 int

Codeforces Round #604 (Div. 2) D、E、F题解

Beautiful Sequence \[ Time Limit: 1000 ms\quad Memory Limit: 256 MB \] 首先我们可以考虑到 \(0\) 只能 和 \(1\) 放在一起.\(3\) 只能和 \(2\) 放在一起,那么我们想办法先把 \(0\) 和 \(3\) 凑出来,最后就剩下 \(1\) 和 \(2\) 了,我们只要把他们放在一起就可以了. 所以我们可以贪心考虑三个 \(string\),分别长成 \(0101...0101\).\(2323...2323\

Codeforces Round #604 (Div. 2)(A-E)

A. Beautiful String 题意:把'?'换成'a' or 'b' or 'c'使得相邻的两个字符不相同. 暴力枚举每个'?'前后. #include <bits/stdc++.h> using namespace std; const int MAXN=1e5+10; string s; int main(){ ios::sync_with_stdio(false); int T; cin>>T; while(T--){ cin>>s; bool ok=t

CF 600B Queries about less or equal elements --- 二分查找

CF 600B 题目大意:给定n,m,数组a(n个数),数组b(m个数),对每一个数组b中的元素,求数组a中小于等于数组该元素的个数. 解题思路:对数组a进行排序,然后对每一个元素b[i],在数组a中进行二分查找第一个大于b[i]的位置即为结果 /* CF 600B Queries about less or equal elements --- 二分查找 */ #include <cstdio> #include <algorithm> using namespace std;

cf Beautiful numbers(数位dp)

Beautiful numbers Time Limit:4000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 55D Description Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number i

CF 55D Beautiful numbers (数位DP)

题意: 如果一个正整数能被其所有位上的数字整除,则称其为Beautiful number,问区间[L,R]共有多少个Beautiful number?(1<=L<=R<=9*1018) 思路: 数字很大,不能暴力.但是想要知道一个数是否为Beautiful number时,至少得等到它的所有位都出现吧?不然如何确定其实可以被整除的呢? 分析一下,类似2232和3232等这样的数字,这两个只是出现了2和3而已,他们的lcm都是6,所以有可以压缩统计的地方就是lcm,开一维来存储.接下来考虑

数位DP CF 55D Beautiful numbers

题目链接 题意:定义"beautiful number"为一个数n能整除所有数位上非0的数字 分析:即n是数位所有数字的最小公倍数的倍数.LCM(1到9)=2520.n满足是2520的约数的倍数.dp[len][val][lcm]一维为数的位数,一维为%2520的值(保存原数不可能,也没必要,2520是可行的最小公倍数最大的一个),一维为当前数位的lcm,判断满足的条件是val%lcm==0.这题离散化2520的约数,否则空间开不下. #include <bits/stdc++.

CF 55D - Beautiful numbers(数位DP)

题意: 如果一个数能被自己各个位的数字整除,那么它就叫 Beautiful numbers.求区间 [a,b] 中 Beautiful numbers 的个数. 分析:先分析出,2~9 的最大的最小公倍数是 2520({5,7,8,9}),先预处理出所有可能的最小公倍数m[c] dp[i][d][c]表示长度i, 余数d,最小公倍数是m[c]的个数. #include<cstdio> #include<cstring> #define mod 2520 ll dp[35][2520