HDU-6825 Set1

Here

题意:

1-N这N个数形成的集合,每次操作从集合里面删掉一个当前最小的数,然后随机删掉剩下的数中的一个数。问你1-N每个数最终剩下来的概率是多少。

解题思路

首先考虑每次删除的本质,其实就是把当前最小的数和剩下的数中的一个做一个绑定,所以可以从这方面入手。对于1~ n 2 \lfloor\frac{n}{2}\rfloor 的数,显然他们最后留下的概率是0。考虑剩下的那些数,假设现在n是11,我们现在在算第8个数的概率,那么现在8的前面有7个数,8的后面有3个数。对于在8后面的这3个数,他们只能作为随机删掉的数。这样一来,那么前面的7个数里面是有3个数和后面的这3个数对应的,并且配对方式是一个 A 3 3 A_{3}^{3} 的排列。接下来再考虑前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}

Code

/****************************
* Author : 水娃             *
* Date : 2020-08-04-15.27.23*
****************************/
#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;
}
/*
*/

猜你喜欢

转载自blog.csdn.net/qq_43807662/article/details/107797877