(这送分题我写不出来……我退役吧)
也懒得写题解了,看吧。
什么你说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#include #include #include #include #include #include #include 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 =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。 +
+欢迎访问我的博客:+
+++++++++++++++++++++++++++++++++++++++++++