2020 HDU Multi-University Training Contest 5

2020 HDU Multi-University Training Contest 5

1001 Tetrahedron

链接:HDU6814 Tetrahedron

题意
  • 给定直角三棱锥的三边 a , b , c ∈ [ 1 , n ] a, b, c \in [1, n] a,b,c[1,n] ,求到底面高 h h h平方倒数的期望
思路
  • 1 h 2 = 1 a 2 + 1 b 2 + 1 c 2 \dfrac{1}{h^2} = \dfrac{1}{a^2} + \dfrac{1}{b^2} + \dfrac{1}{c^2} h21=a21+b21+c21
  • 预处理出 E ( 1 a 2 ) E(\dfrac{1}{a^2}) E(a21)
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 6e6 + 7;
const int MOD = 998244353;
// const int INF = ;
// const int DIRX[] = {};
// const int DIRY[] = {};

int ept[MAXN];

inline int getpow(int a, int b)
{
    int ret = 1;
    for (; b; b >>= 1, a = a * a % MOD)
        if (b & 1)
            ret = ret * a % MOD;
    return ret;
}

void pre()
{
    int tmp = 0;
    for (int i = 1; i <= 6e6; ++i)
    {
        tmp += getpow(i * i % MOD, MOD - 2);
        tmp %= MOD;
        ept[i] = tmp;
    }
}

int T;
int n;
int ans;

int32_t main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    pre();
    cin >> T;
    while (T--)
    {
        cin >> n;
        ans = (3 * ept[n] % MOD) * getpow(n, MOD - 2) % MOD;
        cout << ans << endl;
    }
    return 0;
}
1003 Boring Game

链接:HDU6816 Boring Game

思路
  • 模拟:判断正反面、属于那张纸。

想象 n n n张纸展开的情况,每次截取上半部分,倒置(左转 9 0 ∘ 90 ^ \circ 90 )后将其放置于剩余部分的左侧,模拟 k k k 次即可。

1009 Paperfolding

链接:HDU6822 Paperfolding

代码
#include<iostream>
#include<algorithm>
using namespace std;
const long long MOD = 998244353;
long long qpow(long long n, long long p) {
    long long ret = 1;
    for (; p; p >>= 1, n = n * n % MOD)
        if (p & 1)
            ret = ret * n % MOD;
    return ret;
}
long long inv(long long a) {
    return qpow(a, MOD - 2);
}
int main()
{
    int T;
    long long n;
    cin>>T;
    while(T--){
        scanf("%lld",&n);
        long long res, tt, ni;
        res = qpow(2,n);
        tt = 2*qpow(3,n);
        ni = inv(res);
        tt = tt * ni % MOD;
        res += tt + 1;
        res %= MOD;
        printf("%lld\n",res);
    }
    return 0;
}
1012 Set1

链接:HDU6825 Set1

思路
  • 组合数学: c n t [ i ] = C i − 1 n − i ∗ ( n − i ) ! ∗ ∏ k = 0 2 ⋅ i − n − 1 C 2 ⋅ i − n − 1 − k 2 ( 2 ⋅ i − n − 1 2 ) ! cnt[i] = C_{i - 1}^{n - i} * (n - i)! * \dfrac{\prod\limits_{k = 0}^{2 \cdot i - n - 1}C_{2 \cdot i - n - 1 - k}^{2}}{(\frac{2 \cdot i - n - 1}{2})!} cnt[i]=Ci1ni(ni)!(22in1)!k=02in1C2in1k2
    • i i i 号后 n − i n - i ni 个必然是被删除的,在前 i − 1 i - 1 i1 个位置中选择 n − i n - i ni 个与后 n − i n - i ni 个组合,共有 C i − 1 n − i ⋅ ( n − i ) ! C_{i - 1}^{n - i} \cdot (n - i)! Ci1ni(ni)! 种组合
    • 剩余 i − 1 − ( n − i ) = 2 ⋅ i − n − 1 i - 1 - (n - i) = 2 \cdot i - n - 1 i1(ni)=2in1 中选 2 2 2 个为 ∏ k = 0 2 ⋅ i − n − 1 C 2 ⋅ i − n − 1 − k = ( 2 ⋅ i − n − 1 ) ! 2 2 ⋅ i − n − 1 2 \prod\limits_{k = 0}^{2 \cdot i - n - 1}C_{2 \cdot i - n - 1 - k} = \dfrac{(2 \cdot i - n - 1)!}{2^{\frac{2 \cdot i - n - 1}{2}}} k=02in1C2in1k=222in1(2in1)!,又对于每种两两组合其中被删除的必然按从小到大排序,故应 ( 2 ⋅ i − n − 1 2 ) ! (\frac{2 \cdot i - n - 1}{2})! (22in1)! 重复计算的次数
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 5e6 + 7;;
const int MOD = 998244353;
// const int INF = ;
// const int DIRX[] = {};
// const int DIRY[] = {};

int fac[MAXN], inv[MAXN], facinv[MAXN];

void getinv(int n)
{
    fac[0] = 1;
    for (int i = 1; i < n; i++)
        fac[i] = fac[i - 1] * i % MOD;
   	// Factorial
    inv[1] = 1;
    for (int i = 2; i < n; i++)
        inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
    facinv[0] = 1;
    for (int i = 1; i < n; i++)
        facinv[i] = inv[i] * facinv[i - 1] % MOD;
    // Factorials' Muiltiplicative Inverse
}

inline int C(int n, int m)
{
    if (m > n)
        return 0;
    return fac[n] * facinv[m] % MOD * facinv[n - m] % MOD;
}
// C_n^m

inline int getpow(int a, int b)
{
    int ret = 1;
    for (; b; b >>= 1, a = a * a % MOD)
        if (b & 1)
            ret = ret * a % MOD;
    return ret;
}

int T;
int n;
int tmp;
int ans;
int cnt[MAXN];
int sum;

int32_t main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    getinv(MAXN);
    cin >> T;
    while (T--)
    {
        cin >> n;
        sum = 0;
        for (int i = 1; i <= n; ++i)
        {
            if (i <= n / 2)
                cnt[i] = 0;
            else
            {
                cnt[i] = C(i - 1, n - i) * fac[n - i] % MOD
                     * fac[2 * i - n - 1] % MOD
                     * facinv[(2 * i - n - 1) / 2] % MOD
                     * getpow(getpow(2, (2 * i - n - 1) / 2), MOD - 2) % MOD;
                sum = (sum + cnt[i]) % MOD;
            }
        }
        sum = getpow(sum, MOD - 2);
        for (int i = 1; i <= n; ++i)
        {
            ans = cnt[i] * sum % MOD;
            cout << ans << (i == n ? "\n" : " ");
        }
    }
    return 0;
}
1007 Tree

链接:HDU6820 Tree
(待补)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值