Here
题意:
1-N这N个数形成的集合,每次操作从集合里面删掉一个当前最小的数,然后随机删掉剩下的数中的一个数。问你1-N每个数最终剩下来的概率是多少。
解题思路
首先考虑每次删除的本质,其实就是把当前最小的数和剩下的数中的一个做一个绑定,所以可以从这方面入手。对于1~ ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor ⌊2n⌋的数,显然他们最后留下的概率是0。考虑剩下的那些数,假设现在n是11,我们现在在算第8个数的概率,那么现在8的前面有7个数,8的后面有3个数。对于在8后面的这3个数,他们只能作为随机删掉的数。这样一来,那么前面的7个数里面是有3个数和后面的这3个数对应的,并且配对方式是一个 A 3 3 A_{3}^{3} A33的排列。接下来再考虑前7个数里面剩下的4个数,这4个数也是两两配对删掉的,可以利用高中的分堆公式。那么接下来就可以得到公式了
设当前位置前面的数有s1个,后面的数有s2个。
C s 1 s 2 ∗ A s 2 s 2 ∗ C s 1 − s 2 2 ∗ C s 1 − s 2 − 2 2 ∗ C s 1 − s 2 − 4 2 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ C 2 2 ( s 1 − s 2 2 ) ! ( n − 1 ) ∗ ( n − 3 ) ⋅ ⋅ ⋅ ⋅ ⋅ 2 \frac{C_{s1}^{s2}*A_{s2}^{s2}*\frac{C_{s1-s2}^{2}*C_{s1-s2-2}^{2}*C_{s1-s2-4}^{2}······C_{2}^{2}}{(\frac{s1-s2}{2})!}}{(n-1)*(n-3)·····2} (n−1)∗(n−3)⋅⋅⋅⋅⋅2Cs1s2∗As2s2∗(2s1−s2)!Cs1−s22∗Cs1−s2−22∗Cs1−s2−42⋅⋅⋅⋅⋅⋅C22
Code
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
#define ll long long
#define debug(a) cout<<#a<<" is "<<a<<"\n"
#define ull unsigned long long
#define fi first
#define se second
typedef pair<int,int>pii;
typedef pair<ll,int>pli;
typedef pair<int,ll>pil;
typedef pair<ll,ll>pll;
const ll mo=998244353;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
namespace FAST_IO {
#define IN_LEN 250000
#define OUT_LEN 250000
//以上两个值无需修改
inline char Getchar() {
static char buf[IN_LEN], *l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,IN_LEN,stdin);
return (l==r)?EOF:*l++;
}
char obuf[OUT_LEN], *ooh = obuf;
inline void Putchar(char c) {
if (ooh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout),ooh = obuf;
*ooh++ = c;
}
inline ll rd(){
ll x=0;int ch=Getchar(); bool f=1;
while (!isdigit(ch)&&(ch!='-')&&(ch!=EOF)) ch=Getchar();
if (ch=='-'){f=0;ch=Getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=Getchar();}
return f?x:-x;
}
void write(ll x){ if (x>=10) write(x/10),Putchar((char)(x%10+'0')); else Putchar((char)(x+'0')); }
inline void flush() { fwrite(obuf, 1, ooh - obuf, stdout); }
}
using namespace FAST_IO;
const int MAXN = 6e6 + 5;
ll fac[MAXN + 100], inv_fac[MAXN + 100],inv[MAXN+100];///fac是分子,inv是分母
ll fpow(ll a, ll p)
{
ll ans = 1;
a=a%mo;
for (; p; p >>= 1) {
if (p & 1)
ans = ans * a%mo;
a = a * a%mo;
}
return ans;
}
void init() {
fac[0] = 1;
for (int i = 1; i <= MAXN; i++) {
fac[i] = fac[i - 1] * i%mo;
}
inv_fac[MAXN] = fpow(fac[MAXN], mo - 2);
for (int i = MAXN - 1; i >= 0; i--) {
inv_fac[i] = inv_fac[i + 1] * (i + 1) % mo;
}
for(int i=1;i<=MAXN;i++){
inv[i]=inv_fac[i]*fac[i-1]%mo;
}
}
ll C(ll m, ll n)///组合
{
return fac[m] * inv_fac[m - n] % mo*inv_fac[n] % mo;
}
ll P(ll m, ll n)///排列
{
return fac[m] * inv_fac[m - n] % mo;
}
ll C_tmp[MAXN],A_inv[MAXN];
void prework()
{
C_tmp[0]=1;
for(ll i=1;i<=2500000;i++)
{
C_tmp[i]=C_tmp[i-1]*C(i*2,2)%mo;
}
A_inv[1]=1;
for(int i=3;i<=5000000;i+=2)
{
A_inv[i]=A_inv[i-2]*(ll)(i-1)%mo;
}
A_inv[5000000-1]=fpow(A_inv[5000000-1],mo-2);
for(int i=5000000-3;i>=0;i-=2)
{
A_inv[i]=A_inv[i+2]*(ll)(i+1)%mo;
}
}
void work()
{
int n;
n=rd();
for(ll i=1;i<=n;i++)
{
if(i*2<n)
{
write(0);
Putchar(' ');
}
else
{
ll ans=1,s1=i-1,s2=n-i;
ans=ans*C(s1,s2)%mo*P(s2,s2)%mo*C_tmp[(s1-s2)/2]%mo;
ans=ans*inv_fac[(s1-s2)/2]%mo;
ans=ans*A_inv[n]%mo;
write(ans);
if(i==n)Putchar('\n');
else Putchar(' ');
}
}
}
int main()
{
init();
prework();
int T;T=rd();while(T--)
work();
flush();
return 0;
}