Everything Is Generated In Equal Probability HDU 6595(期望dp)

大致题意

好像是给一个数字n,然后随机选择一个1到n的数字,对其排列进行这样一种运算。首先res加上当前排列的逆序对数,然后再随机选择当前数列的子序列,继续进行该运算直到子序列长度为0。求res的期望值。(1<=n<=3000)

思路

本蒟蒻几乎没有写过期望dp的题。每次都是做题的时候一点思路也没有,看题解就觉得很有道理。首先对于一个长度为n的随机排列,总共有c(n,2)的数对,因为随机的缘故,所以期望的逆序对数就是c(n,2)/2。然后其子序列也是同样的做法。对于一个长度为j的子序列,则有c(n,j)种。所以 fi = c(i,2)/2 + sum_ j( c(i,j) * fj )/2^i
可以发现求 fi的式子里有fi, 然后可以把右边和式里的fi拎出来放到左边。
然后就可以预处理一下1-3000,然后求个点缀和。之后只要O(1)查询即可。

感觉期望dp常常要往随机,平均 考虑,最后就是所有的价值分别乘上他们的概率。

代码
#include<bits/stdc++.h>
using namespace std;
#define maxn 3005
#define maxm 1000006
#define ll long long int
#define INF 0x3f3f3f3f
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
#define mem(a) memset(a,0,sizeof(a))
#define sqr(x) (x*x)
#define inf (ll)2e18+1
#define PI acos(-1)
#define mod 998244353
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
     while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
     return f*x;
}
int n;
ll fac[maxn],ifac[maxn],inv2[maxn],f[maxn];
ll fast(ll x,ll y){
    ll res=1ll;
    while(y){
        if(y&1)res=res*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return res;
}
void init()
{
    fac[0]=fac[1]=1;
    inv2[maxn-1]=fast(fast(2ll,maxn-1),mod-2);
    dec(i,maxn-2,1)inv2[i]=inv2[i+1]*2ll%mod;
    inc(i,2,maxn-1)fac[i]=fac[i-1]*i%mod;
    ifac[maxn-1]=fast(fac[maxn-1],mod-2);
    dec(i,maxn-2,0)ifac[i]=ifac[i+1]*(i+1)%mod;
}
ll c(int x,int y){return fac[x]*ifac[x-y]%mod*ifac[y]%mod;}
int main()
{
    init();
    f[0]=f[1]=0;
    inc(i,2,maxn-1){
        ll tmp=0;
        inc(j,2,i-1)tmp=(tmp+c(i,j)*f[j]%mod)%mod;
        f[i]=(tmp*inv2[i]%mod+c(i,2)*inv2[1]%mod)%mod;
        f[i]=f[i]*fast((1-inv2[i]+mod)%mod,mod-2)%mod;
    }
    inc(i,1,maxn-1)f[i]=(f[i]+f[i-1])%mod;
    while(~scanf("%d",&n)){
        printf("%lld\n",fast(1ll*n,mod-2)*f[n]%mod);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值