BZOJ5340 & 洛谷4564 & LOJ2552:[CTSC2018]假面——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5340
https://www.luogu.org/problemnew/show/P4564
(这送分题我写不出来……我退役吧)
也懒得写题解了,看https://kelin.blog.luogu.org/solution-p4564吧。
什么你说op=1的你没听懂,那你可能和我一样了(握手(大雾。
那么遵从原题解的命名,f[u][i]表示除u以外有i个人活着的概率,g[i]为i个人活着的概率,p[u]表示u活着的概率。
(其实正确的思路应该先想到g数组如何求,然后发现g数组的信息无法落到每个具体人的头上,所以需要f数组。)
则可以发现,g的范围比f大(包括了u活着的可能性),于是需要扣除u活着时候有i个人活着的概率。
所以答案就是g[i]-p[u]*f[u][i-1]了……等等我怎么样例都过不去emmm
其实!这个式子蕴含了一个信息就是保证了u是死的,而实际上我们要求的是不知道u的死活的概率,于是除以(1-p[u])就是答案了。
(然而这个思路可能考场上很难想吧……大部分人应该都是靠推推出来的这个式子,只有我啥也不会……)
#include<cmath> #include<queue> #include<cstdio> #include<cctype> #include<vector> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=205; const int p=998244353; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } inline void write(int x){ if(x>9)write(x/10); putchar(x%10+'0'); } int qpow(int k,int n){ int res=1; while(n){ if(n&1)res=(ll)res*k%p; k=(ll)k*k%p;n>>=1; } return res; } int n,q,f[N][105],g[N],h[N],s[N],inv[N]; inline int add(ll x,int y){ x+=y;if(x>=p)x-=p;return x; } inline int sub(int x,int y){ x-=y;if(x<0)x+=p;return x; } int main(){ n=read(); for(int i=1;i<=n;i++)f[i][read()]=1; inv[1]=1; for(int i=2;i<N;i++)inv[i]=(ll)(p-p/i)*inv[p%i]%p; q=read(); while(q--){ int op=read(); if(!op){ int id=read(),u=read(),v=read(); int P=(ll)u*qpow(v,p-2)%p; f[id][0]=(f[id][0]+(ll)P*f[id][1]%p)%p; for(int i=1;i<=100;i++) f[id][i]=add((ll)sub(1,P)*f[id][i]%p,(ll)P*f[id][i+1]%p); }else{ int k=read(); for(int i=1;i<=k;i++)s[i]=sub(1,f[read()][0]),h[i]=0; h[0]=1; for(int i=1;i<=k;i++) for(int j=i;j>=0;j--) if(!j)h[j]=(ll)sub(1,s[i])*h[j]%p; else h[j]=add((ll)s[i]*h[j-1]%p,(ll)(p+1-s[i])*h[j]%p); for(int i=1;i<=k;i++){ if(!s[i]){putchar('0');putchar(' ');continue;} if(s[i]==1) for(int j=0;j<=k-1;j++)g[j]=h[j+1]; else{ int Inv=qpow(sub(1,s[i]),p-2);g[0]=(ll)h[0]*Inv%p; for(int j=1;j<=k-1;j++){ g[j]=(ll)sub(h[j],(ll)g[j-1]*s[i]%p)*Inv%p; } } int ans=0; for(int j=0;j<=k-1;j++)ans=add(ans,(ll)g[j]*inv[j+1]%p); write((ll)ans*s[i]%p);putchar(' '); } putchar('\n'); } } for(int i=1;i<=n;i++){ int ans=0; for(int j=0;j<=100;j++) (ans+=(ll)f[i][j]*j%p)%=p; write(ans);putchar(' '); } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++