1. 程式人生 > 實用技巧 >2020杭電多校 5I / HDU 6822 - Paperfolding (數學)

2020杭電多校 5I / HDU 6822 - Paperfolding (數學)

HDU 6822 - Paperfolding


題意

將一張紙折\(n\)次,四個方向都可以折

折完後取中點,橫豎分別切一刀(切十字)

問最後紙被分成的數量的期望(模\(998244353\)




思路

可以發現,從左往右與從右往左對答案的影響相同

同理從上往下和從下往上也是相同的

所以四種情況可以合成等概率的兩種情況考慮(橫向與豎向)

可以發現,如果往同一個方向折\(k\)次,對於展開後的紙張在對應方向會出現\(2^k\)條割線,那麼紙將會被分為\(2^k+1\)

假如當前紙總共要折\(n\)次,橫向折\(k\)次,豎向則是\(n-k\)

所以此時紙張會被分成\((2^k+1)*(2^{n-k}+1)\)

考慮到概率,對於“總共要折\(n\)次,橫向折\(k\)次”,也就是在所有折的次數中取\(k\)次是橫向折的,所以出現的次數可以表示成\(C_{n}^{k}\)

又因為折法總共分成了橫向與豎向,所以總共的情況數為\(2^n\)

故期望值就是\(\sum_{k=0}^{n}\frac{C_n^k(2^k+1)(2^{n-k}+1)}{2^n}\)

先只考慮分子部分

將兩個多項式合併,得到\((2^n+1+2^k+2^{n-k})\)

先考慮\(\sum_{k=0}^nC_n^k(2^n+1)\)

由於\(\sum_{k=0}^nC_n^k=2^n\),所以該部分等價於\(2^n(2^n+1)\)

考慮\(\sum_{k=0}^nC_n^k(2^k+2^{n-k})\)

分別乘上\(1^{n-k}\)以及\(1^k\)

得到\(\sum_{k=0}^n(C_n^k2^k1^{n-k}+C_n^k2^{n-k}1^k)\)

合併二項式,得到\((2+1)^n+(2+1)^n=2\times3^n\)

所以整個期望值式子便化簡到了\(\frac{2^n(2^n+1)+2\times3^n}{2^n}=2^n+1+2\times\frac{3^n}{2^n}\)

快速冪加逆元即可




程式碼

(202ms/1000ms)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;

ll qpow(ll a,ll n){
    ll r=1;
    a%=mod;
    while(n)
    {
        if(n&1)
            r=(r*a)%mod;
        n>>=1;
        a=(a*a)%mod;
    }
    return r;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll n;
        scanf("%lld",&n);
        ll n2=qpow(2,n),n3=qpow(3,n),inv2=qpow(n2,mod-2);
        printf("%lld\n",(n2+1+2*n3*inv2)%mod);
    }
    return 0;
}