HDU 6595 Everything Is Generated In Equal Probability(概率+组合数)

题面

One day, Y_UME got an integer NN and an interesting program which is shown below:


Y_UME wants to play with this program. Firstly, he randomly generates an integer n∈[1,N]n∈[1,N] in equal probability. And then he randomly generates a permutation of length nn in equal probability. Afterwards, he runs the interesting program(function calculate()) with this permutation as a parameter and then gets a returning value. Please output the expectation of this value modulo 998244353998244353 .

A permutation of length nn is an array of length nn consisting of integers only ∈[1,n]∈[1,n] which are pairwise different.

An inversion pair in a permutation pp is a pair of indices (i,j)(i,j) such that i>ji>j and pi<pjpi<pj . For example, a permutation [4,1,3,2][4,1,3,2] contains 44 inversions: (2,1),(3,1),(4,1),(4,3)(2,1),(3,1),(4,1),(4,3) .

In mathematics, a subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements. Note that empty subsequence is also a subsequence of original sequence.

Refer to https://en.wikipedia.org/wiki/Subsequence for better understanding.

 

Input

There are multiple test cases.

Each case starts with a line containing one integer N(1≤N≤3000)N(1≤N≤3000) .

It is guaranteed that the sum of NN s in all test cases is no larger than 5×1045×104 .

Output

For each test case, output one line containing an integer denoting the answer.

Sample Input

1
2
3

Sample Output

0
332748118
554580197

题目链接

HDU 6595

题意

输入一个N,使n为1->N中的任意一个数,生成一个元素范围在[1,n],无重复元素的随机排序的序列,对序列进行calculate()运算。

calculate(序列)=序列的逆序对数+calculate(随机的一个子序列)。

分析

总期望=E(各种序列的逆序对数)+E(calculate(随机的一个子序列))

全排列有n!个序列。每两个互为倒序的序列为一对,有\frac{n!}{2}对,每对的逆序对数的和为\frac{n(n-1)}{2},除以序列种数n!

则E(序列的逆序对数)=\frac{n!}{2}*\frac{n(n-1)}{2}*\frac{1}{n!}=\frac{n(n-1)}{4}

设,z[i]为,n取i时的期望。

z[n]=\frac{n(n-1)}{4}+\frac{1}{2^{n}}(C_{n}^{n}(\frac{n(n-1)}{4}+\frac{1}{2^{n}}(\cdot \cdot \cdot ))+C_{n}^{n-1}z[n-1]+C_{n}^{n-2}z[n-2]+\cdot \cdot \cdot \cdot +C_{n}^{1}z[1]]+C_{n}^{0}*0)

C_{n}^{n}=1 

z[n]=\frac{n(n-1)}{4}+\frac{1}{2^{n}}(C_{n}^{n}\frac{n(n-1)}{4}+C_{n}^{n-1}z[n-1]+C_{n}^{n-2}z[n-2]+\cdot \cdot \cdot \cdot +C_{n}^{1}z[1]]+C_{n}^{0}*0)+\frac{1}{(2^{n})^2}(C_{n}^{n}\frac{n(n-1)}{4}+C_{n}^{n-1}z[n-1]+C_{n}^{n-2}z[n-2]+\cdot \cdot \cdot \cdot +C_{n}^{1}z[1]]+C_{n}^{0}*0)+\frac{1}{(2^{n})^3}(C_{n}^{n}\frac{n(n-1)}{4}+C_{n}^{n-1}z[n-1]+C_{n}^{n-2}z[n-2]+\cdot \cdot \cdot \cdot +C_{n}^{1}z[1]]+C_{n}^{0}*0)+\cdot \cdot \cdot

z[n]=\frac{n(n-1)}{4}+(\frac{1}{2^{n}}+\frac{1}{(2^{n})^2}+\frac{1}{(2^{n})^3}+\cdot \cdot \cdot )(C_{n}^{n}\frac{n(n-1)}{4}+C_{n}^{n-1}z[n-1]+C_{n}^{n-2}z[n-2]+\cdot \cdot \cdot \cdot +C_{n}^{1}z[1]]+C_{n}^{0}*0)

s[n]是z[n]的前缀和

answer=\frac{s[N]}{N}

程序

#include<stdio.h>
#include<iostream>
using namespace std;
const long long mod=998244353;
#define maxn 3005
long long fac[maxn];//阶乘
long long finv[maxn];//阶乘的逆元

long long z[maxn];//calculate(n)的期望
long long s[maxn];//前缀和

long long exgcd(long long a,long long b,long long &x,long long &y)//扩展欧几里得算法
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    long long ret=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return ret;
}

long long getinv(long long a)//求a在mod下的逆元,不存在逆元返回-1
{
    long long x,y;
    long long d=exgcd(a,mod,x,y);
    return d==1?(x%mod+mod)%mod:-1;
}

void init()
{
    fac[0]=1;
    for(int i=1;i<maxn;i++)
        fac[i]=fac[i-1]*i%mod;
    finv[maxn-1]=getinv(fac[maxn-1]);
    for(int i=maxn-2;i>=0;i--)
        finv[i]=finv[i+1]*(i+1)%mod;
}

long long combin(long long n,long long m)//求组合数
{
    if(m<0||n<0||n<m)
        return 0ll;
    return fac[n]*finv[m]%mod*finv[n-m]%mod;
}

long long inversion_exp(long long n)
{
    return (n-1)*n%mod*getinv(4ll)%mod;
}

long long pow(long long a,long long b)
{
    long long sum=1;
    a=a%mod;
    while(b>0)
    {
        if(b%2==1)
            sum=(sum*a)%mod;
        b/=2;
        a=(a*a)%mod;
    }
    return sum;
}

long long positive_mod(long long x)
{
    return (x%mod+mod)%mod;
}

void ask_z(long long n)
{
    if(n==1)
    {
        s[n]=z[n]=0;
        return;
    }
    long long exp=inversion_exp(n);
    long long ans=0;
    for(long long i=n;i>=1;i--)
    {
        long long temp;
        if(i==n)
            temp=exp;
        else
            temp=z[i];
        ans+=combin(n,i)*temp%mod;
        ans%=mod;
    }
    long long zi=1;
    long long mu=positive_mod(pow(2 ,n)-1)%mod;
    ans=ans*zi%mod;
    ans=ans*getinv(mu)%mod;
    ans=(ans+exp)%mod;
    z[n]=ans;
    s[n]=(s[n-1]+z[n])%mod;
    return;
}


int main()
{
    init();
    for(int i=1;i<=3000;i++)
        ask_z(i);
    long long N;
    while(scanf("%lld",&N)!=EOF)
    {
        long long answer=s[N]*getinv(N)%mod;
        printf("%lld\n",answer);
    }
    return 0;
}

2019年07月25日 16:28:19

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值