HDU 6825 Set1 2020杭电多校(数学推导)

原题题面

You are given a set S = 1.. n S={1..n} S=1..n. It guarantees that n n n is odd. You have to do the following operations until there is only 1 1 1 element in the set:
Firstly, delete the smallest element of S S S. Then randomly delete another element from S S S.
For each i ∈ [ 1 , n ] i∈[1,n] i[1,n], determine the probability of i i i being left in the S S S.
It can be shown that the answers can be represented by P Q \frac{P}{Q} QP, where P P P and Q Q Q are coprime integers, and print the value of P × Q − 1 m o d   998244353 P×Q^{−1} mod\ 998244353 P×Q1mod 998244353.

输入格式

The first line containing the only integer T ( T ∈ [ 1 , 40 ] ) T(T∈[1,40]) T(T[1,40]) denoting the number of test cases.
For each test case:
The first line contains a integer n .
It guarantees that: ∑ n ∈ [ 1 , 5 × 1 0 6 ] ∑n∈[1,5×10^6] n[1,5×106].

输出格式

For each test case, you should output n n n integers, i − t h i-th ith of them means the probability of i i i being left in the S S S.

输入样例

1
3

输出样例

0 499122177 499122177

题面分析

给一个包含 1 1 1~ n n n n n n元集合 S S S(保证 n n n是奇数),每次先删除最小的数字,再随机删除剩下的一个数字,经过若干轮删除后会留下一个数 i i i,求每个 i i i留下来的概率。
易知[1, ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor 2n]留下来概率是0,因为在 n 2 \frac{n}{2} 2n轮的删除中它们必定被删除。
故接下来只要考虑[ ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor 2n+1,n]。
稍加打表可以发现
第一项是 ( ⌊ n 2 ⌋ ) ! 2 ⌊ n 2 ⌋ ∗ ⌊ n 2 ⌋ ! \frac{(\lfloor \frac{n}{2} \rfloor )!}{2^{\lfloor \frac{n}{2} \rfloor}*\lfloor \frac{n}{2} \rfloor!} 22n2n!(2n)!
第二项是 ( ⌊ n 2 ⌋ + 1 ) ! 2 ∗ 2 ⌊ n 2 ⌋ ∗ ⌊ n 2 ⌋ ! \frac{(\lfloor \frac{n}{2} \rfloor+1)!}{2*2^{\lfloor \frac{n}{2} \rfloor}*\lfloor \frac{n}{2} \rfloor!} 222n2n!(2n+1)!
第三项是 ( ⌊ n 2 ⌋ + 2 ) ! 2 ∗ 4 ∗ 2 ⌊ n 2 ⌋ ∗ ⌊ n 2 ⌋ ! \frac{(\lfloor \frac{n}{2} \rfloor+2)!}{2*4*2^{\lfloor \frac{n}{2} \rfloor}*{\lfloor \frac{n}{2} \rfloor}!} 2422n2n!(2n+2)!
故第 i i i项为 ( ⌊ n 2 ⌋ + ( i − 1 ) ) ! 2 i − 1 ∗ ( i − 1 ) ! ∗ 2 ⌊ n 2 ⌋ ∗ ⌊ n 2 ⌋ ! \frac{(\lfloor \frac{n}{2} \rfloor+(i-1))!}{2^{i-1}*(i-1)!*2^{\lfloor \frac{n}{2} \rfloor}*{\lfloor \frac{n}{2} \rfloor}!} 2i1(i1)!22n2n!(2n+(i1))!
化简得 ( ⌊ n 2 ⌋ + ( i − 1 ) ) ! 2 i − 1 ∗ ( i − 1 ) ! ∗ 2 ⌊ n 2 ⌋ ∗ ⌊ n 2 ⌋ ! ( n ≥ 2 ) \frac{(\lfloor \frac{n}{2} \rfloor+(i-1))!}{2^{i-1}*(i-1)!*2^{\lfloor \frac{n}{2} \rfloor}*{\lfloor \frac{n}{2} \rfloor}!}(n\geq2) 2i1(i1)!22n2n!(2n+(i1))!(n2)
证明不会,见出题人题解

AC代码(2074ms)

#include 
using namespace std;
const long long mod=998244353;
const long long maxn=5e6;
long long factor[maxn+10];
long long invn[maxn+10];
long long invFactor[maxn+10];
long long invpow2[maxn+10];
void init ()
{
    factor[0]=invFactor[0]=invn[0]=factor[1]=invFactor[1]=invn[1]=1;
    for (int i=2;i<=maxn;i++)
    {
        factor[i]=(long long)factor[i-1]*i%mod;
        invn[i]=(long long) (mod-mod/i)*invn[mod%i]%mod;
        invFactor[i]=(long long)invFactor[i-1]*invn[i]%mod;
    }
    invpow2[0]=1;
    for (int i=1;i<=maxn;i++)
    {
        invpow2[i]=(long long) invpow2[i-1]*invn[2]%mod;
    }
}
void solve1 ()
{
    init ();
    int t;
    scanf ("%d",&t);
    while (t--)
    {
        long long n;
        scanf ("%lld",&n);
        if(n==1)
        {
            printf ("1\n");
            continue;
        }
        for (int i=1;i<=n/2;i++)
        {
            printf ("0 ");
        }
        long long num=(long long) invFactor[n/2]*invpow2[n/2]%mod;
        for (long long i=1;i<=n/2+1;i++)
        {
            long long ans=factor[n/2+i-1];
            long long sumb=(long long)invpow2[i-1]*invFactor[i-1]%mod;
            ans=(long long)ans*num%mod;
            if(i!=1)
                ans=(long long)sumb*ans%mod;
            printf ("%lld",ans);
            if(i!=n/2+1)
                printf (" ");
        }
        printf ("\n");
    }
}
int main ()
{
//    ios_base::sync_with_stdio(false);
//    cin.tie(0);
//    cout.tie(0);
#ifdef ACM_LOCAL
    freopen ("in.txt","r",stdin);
    freopen ("out.txt","w",stdout);
    long long test_index_for_debug=1;
    char acm_local_for_debug;
    while (cin>>acm_local_for_debug)
    {
        cin.putback (acm_local_for_debug);
        if (test_index_for_debug>100)
        {
            throw runtime_error ("Check the stdin!!!");
        }
        auto start_clock_for_debug=clock ();
        solve1 ();
        auto end_clock_for_debug=clock ();
        cout<<"\nTest "<<test_index_for_debug<<" successful"<<endl;
        cerr<<"Test "<<test_index_for_debug++<<" Run Time: "
            <<double (end_clock_for_debug-start_clock_for_debug)/CLOCKS_PER_SEC<<"s"<<endl;
        cout<<"--------------------------------------------------"<<endl;
    }
#else
    solve1();
#endif
    return 0;
}

后记

赛前唯唯诺诺,赛后五分钟推出答案…
题面里的 [ 1 , 5 × 1 0 6 ] [1,5×10^6] [1,5×106]一直看成 1.5 ∗ 1 0 6 1.5*10^6 1.5106,RE穿了…
DrGilbert 2020.8.4

你可能感兴趣的:(数论)