题目:
给出一个数n,在【1,n】等概率的选择一个数i,在【1,i】内每次等概率的选择一个数字组成长度为i的序列,这个序列中所有数都在【1,i】内,且两两互不相同(也就是说这个长度为i的序列是1->n的一种排列),以这个长度为i的序列为参数array运行程序:
1.统计array中的逆序对数目
2.统计array的子序列的逆序对数目(子序列的长度为0->length(array)),
3.array长度为0结束程序,否则以这个子序列为参数array运行程序,重复1,2
求最终逆序对数目的期望值,对998244353取模
程序如下:
input:
0
1
2
output:
0
332748118
554580197
SOLUTION:
对于这种无限向里递归,我们可以套路的使用递推来推出来
CODE:
#include<bits/stdc++.h> using namespace std; #define lowbit(x) ((x)&(-x)) typedef long long ll; const int maxn = 3005; const int mod = 998244353; ll mu[maxn], zi[maxn], f[maxn], c[maxn][maxn]; ll qkpow(ll a,ll p,ll mod) { ll t=1,tt=a%mod; while(p) { if(p&1)t=t*tt%mod; tt=tt*tt%mod; p>>=1; } return t; } ll getInv(ll a,ll mod) { return qkpow(a,mod-2,mod); } void init() { //组合数 for(int i = 1; i < maxn;i++) { c[i][i] = 1, c[i][0] =1; for(int j = 1; j < i; j++) c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod; } //分母 mu[1] = 2; for(int i = 2; i < maxn; i++) mu[i] = (mu[i - 1] * 2) % mod; f[0] = 0, f[1] = 0; for(int i = 2; i < maxn; i++) { //或者不用单开一个分子数组,存到f[i]里 zi[i] = (c[i][2] * mu[i-1]) % mod;//原序列的逆序对期望值!!不要写成c[i][2]/2 * mu[i-1] 因为c[2][2]/2=0,而应该是0.5 zi[i]=0; for(ll j = 0; j < i; j++) zi[i] = (zi[i] + (c[i][j] * f[j]) % mod) % mod; f[i] = (zi[i] * getInv(mu[i] -1 , mod)) % mod;//得到第二个式子的f[i] f[i] += (1ll*c[i][2] * mu[i-1]%mod*getInv(mu[i]-1,mod)) % mod; f[i] %=mod; //p rintf("f[%d]: %lld\n", i, f[i]); } } int main() { ios::sync_with_stdio(false); int x; init(); while(cin >> x) { int ans = 0; for(int i = 1; i <= x; i++) ans = (ans + f[i]) % mod; ans = (ans * getInv(x, mod) ) % mod; cout << ans << endl; } return 0; }