• Codeforces 1264C/1265E Beautiful Mirrors with queries (概率期望、DP)


    题目链接

    http://codeforces.com/contest/1264/problem/C

    题解

    首先显然断点把序列分成几部分,总答案就等于所有部分的答案之和。考虑如何求一部分内的答案。首先有个非常经典的dp是(f_i)表示期望多少次从(i)走到(i+1), 但是按此方法并不能(至少我不会)导出一个方便维护修改的做法。
    这时可以转换思路,考虑另一种DP,设(f_i)表示(i)这个点期望经过多少次,则有(f_i=frac{1}{p_i}f_{i+1}, f_{n+1}=1), 即(f_i=frac{1}{prod^n_{j=i}p_j}).
    然后就很容易维护了,只需要求后缀积及其后缀和即可。每次二分前驱后继,算一算贡献差即可。
    时间复杂度(O(nlog n)).

    代码

    #include<bits/stdc++.h>
    #define llong long long
    using namespace std;
    
    const int N = 2e5;
    const int P = 998244353;
    set<int> b;
    llong p[N+3];
    llong s[N+3],ss[N+3];
    bool f[N+3];
    int n,q; llong ans;
    
    llong quickpow(llong x,llong y)
    {
    	llong cur = x,ret = 1ll;
    	for(int i=0; y; i++)
    	{
    		if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}
    		cur = cur*cur%P;
    	}
    	return ret;
    }
    llong mulinv(llong x) {return quickpow(x,P-2);}
    
    int getprv(int x) {set<int>::iterator iter=b.lower_bound(x); iter--; return *iter;}
    
    void Flip(int x)
    {
    	int l = getprv(x),r = *b.upper_bound(x);
    	llong tmp = (ss[l]-ss[x]+P)%P,coe = f[x]==0?(s[x]-s[r]+P)%P:(s[r]-s[x]+P)%P;
    	ans = (ans+tmp*coe)%P;
    	if(!f[x]) {b.insert(x);} else {b.erase(x);}
    	f[x]^=1;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&q);
    	for(int i=1; i<=n; i++) {scanf("%lld",&p[i]); p[i] = p[i]*mulinv(100)%P;}
    	b.insert(1); b.insert(n+1); f[1] = 1;
    	s[n+1] = 1ll; for(int i=n; i>=1; i--) {s[i] = s[i+1]*p[i]%P; ss[i] = (mulinv(s[i])+ss[i+1])%P;}
    	ans = ss[1];
    	for(int i=1; i<=q; i++)
    	{
    		int x; scanf("%d",&x);
    		Flip(x);
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    IOS调试问题集
    sql常用语句及日期格式
    事件的简单面试题
    首博
    T-SQL查询进阶--详解公用表表达式(CTE)
    c++分布式计算类库
    MSSQL on Linux
    使用supervisor实现.NET Core程序后台运行
    CentOS下安装Nginx并安装服务实现自启动
    macOS安装MongoDB
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11996219.html
Copyright © 2020-2023  润新知