首页 > 其他分享 >P6046 纯粹容器

P6046 纯粹容器

时间:2023-01-09 15:35:56浏览次数:68  
标签:&& 容器 P6046 int 容斥 纯粹 ans 干掉 mod

P6046 纯粹容器

关键

计算ai在第i回合死的概率,并且乘上i-1,就是一个贡献值。
但是直接求解在第i回合结束的概率是比较难的,因为战斗顺序是不确定的,所以不能直接求。但是可以求出在第i轮内结束的概率,然后利用容斥,和前面见一下就可以了。
如果这个人要死,只能由左边第一个的比他大的,或者右边第一个的比他大的杀他,(如果这个比他大的被干掉了,留下的还是一个比他大的),所以可以直接排列组合,左边干掉的概率+右边干掉的概率-重合的,也就是两边都打。然后再利用容斥,与前面相减就可以了。

代码

//数学真的就是我的痛
//被左边薄纱的期望+被右边薄纱的期望-被两个人薄纱的期望
//通常使用容斥,我不懂这个的定义为什么是前j轮干掉,而不是在第j轮干掉
//因为我选的规则不好确定,所以是需要容斥的,保证一定是最后干掉
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
const int M=55;

int kpow(int a,int b) {
    int ans=1;
    while(b) {
        if(b&1)ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}

int inv(int a) {
    return kpow(a,mod-2);
}

int C[55][55];
void init() {
    for(int i=0;i<=50;i++)
        for(int j=0;j<=i;j++) {
            if(j==0||j==i)C[i][j]=1;
            else C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
        }
}

int a[M],b[M],ans[M];

signed main() {
    init();
    int n;cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++) {
        int L=i,R=i;
        for(int j=i-1;j>=1;j--)if(a[j]>a[i]){L=j;break;}
        for(int j=i+1;j<=n;j++)if(a[j]>a[i]){R=j;break;}
        L=i-L,R=R-i;
        if(L==0&&R==0){ans[i]=n-1;continue;}
        for(int j=1;j<n;j++) {
            b[j]=0;
            if(L&&j>=L)b[j]=(b[j]+C[n-1-L][j-L]*inv(C[n-1][j])%mod)%mod;
            if(R&&j>=R)b[j]=(b[j]+C[n-1-R][j-R]*inv(C[n-1][j])%mod)%mod;
            if(L&&R&&j>=L+R)b[j]=(b[j]-C[n-1-L-R][j-L-R]*inv(C[n-1][j])%mod+mod)%mod;
            ans[i]=(ans[i]+(b[j]-b[j-1])*(j-1)%mod+mod)%mod;
        }
        //cout<<endl;
    }
    for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
    return 0;
}

标签:&&,容器,P6046,int,容斥,纯粹,ans,干掉,mod
From: https://www.cnblogs.com/basicecho/p/17037194.html

相关文章