2020杭电多校第五场 Paperfolding(折纸,组合数学)

Problem Description
There is a piece of paper in rectangular shape with sufficient length and width (lay flat on the table). Execute an operation instruction according to a string of length n from left to right that only contains 4 different characters of L,R,U,D.

  1. L instruction means to fold it from left to right,

  2. R instruction means to fold from right to left,

  3. U instruction means to fold from top to bottom,

  4. D instruction means to fold in half from bottom to top.

Note that the operation is limited due to the limitation of the desktop. Namely, the fold operation is restricted. For example, if you fold the paper from left to right, you should let the left side overlap on the right side with no rotation.

Now, cut a knife horizontally (completely cut) at the center of the visible part of the paper, and then cut vertically (completely cut).

The number of pieces of the whole paper split is num(S).

See the example and the picture for better understanding.

Now given a nonnegative integer n, the string S is generated from 4n different possible outcomes in equal probability. Find the expected value of the number of pieces of the paper which is split, that is E(num(S)) mod 998244353.

It can be shown that the answers can be represented by PQ, where P and Q are coprime integers, and print the value of P×Q−1 mod 998244353.

Input
The first line contains a single integer T (1≤T≤105), the number of testcases.

Each of the next T lines contains a number n ( 0≤n≤1018 ).

Output
For each testcase, print the answer in one line.

Sample Input
2
0
1

Sample Output
4
6

题意:
折纸,折了m次以后横着一刀竖着一刀切,求最后分成多少块。

思路:
将折弯后的纸切的刀转到原来的纸上。
那么你往左(右)折x次,原来的纸竖着就会多切 2 x 2^x 2x刀。往上(下)折y次,原来的纸横着就会多切 2 y 2^y 2y刀。因为左右折(上下折)是等价的,所以可以把左右折当做竖着折,上下折当做横着折)

所以最后的块数是 ( x + 1 ) ∗ ( y + 1 ) (x+1)*(y+1) (x+1)(y+1)
我们只需要枚举最终纸横着切了多少刀,竖着切了多少刀即可。
所以结果是 ( n i ) ∗ ( 2 i + 1 ) ∗ ( 2 n − i + 1 ) \tbinom{n}{i}*(2^{i}+1)*(2^{n-i}+1) (in)(2i+1)(2ni+1)

展开再化简就可以得到
2 k ∗ ( 2 k + 1 ) + 3 k ∗ 2 {2^k*(2^k+1)+3^{k}*2} 2k(2k+1)+3k2

因为一共有 2 k 2^k 2k种可能(可以横着折也可以竖着折),所以最终结果是:
2 k ∗ ( 2 k + 1 ) + 3 k ∗ 2 2 k \frac{2^k*(2^k+1)+3^{k}*2}{2^{k}} 2k2k(2k+1)+3k2

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <iostream>
#include <map>
#include <string>

using namespace std;

typedef long long ll;

const int mod = 998244353;
const int maxn = 1e5 + 7;

ll fac[maxn],inv[maxn];

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

ll C(ll n,ll m)
{
    if(m > n || m < 0)
        return 0;
    return fac[n] * ((inv[n - m] * inv[m]) % mod) % mod;
}

void init()
{
    fac[0] = 1;
    inv[0] = 1;
    for(int i = 1;i <= maxn - 2;i++)
    {
        fac[i] = (fac[i - 1] * i) % mod;
        inv[i] = qpow(fac[i],mod - 2);
    }
}


ll gcd(ll x,ll y) {
    return y == 0 ? x : gcd(y,x % y);
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值