题面
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
题目链接
题意
输入一个N,使n为1->N中的任意一个数,生成一个元素范围在[1,n],无重复元素的随机排序的序列,对序列进行calculate()运算。
calculate(序列)=序列的逆序对数+calculate(随机的一个子序列)。
分析
总期望=E(各种序列的逆序对数)+E(calculate(随机的一个子序列))
全排列有n!个序列。每两个互为倒序的序列为一对,有对,每对的逆序对数的和为,除以序列种数n!
则E(序列的逆序对数)=
设,z[i]为,n取i时的期望。
s[n]是z[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