2020 HDU Multi-University Training Contest 5
1001 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
思路
- 模拟:判断正反面、属于那张纸。
想象 n n n张纸展开的情况,每次截取上半部分,倒置(左转 9 0 ∘ 90 ^ \circ 90∘ )后将其放置于剩余部分的左侧,模拟 k k k 次即可。
1009 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]=Ci−1n−i∗(n−i)!∗(22⋅i−n−1)!k=0∏2⋅i−n−1C2⋅i−n−1−k2
- 第 i i i 号后 n − i n - i n−i 个必然是被删除的,在前 i − 1 i - 1 i−1 个位置中选择 n − i n - i n−i 个与后 n − i n - i n−i 个组合,共有 C i − 1 n − i ⋅ ( n − i ) ! C_{i - 1}^{n - i} \cdot (n - i)! Ci−1n−i⋅(n−i)! 种组合
- 剩余 i − 1 − ( n − i ) = 2 ⋅ i − n − 1 i - 1 - (n - i) = 2 \cdot i - n - 1 i−1−(n−i)=2⋅i−n−1 中选 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=0∏2⋅i−n−1C2⋅i−n−1−k=222⋅i−n−1(2⋅i−n−1)!,又对于每种两两组合其中被删除的必然按从小到大排序,故应除 ( 2 ⋅ i − n − 1 2 ) ! (\frac{2 \cdot i - n - 1}{2})! (22⋅i−n−1)! 重复计算的次数
代码
#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
(待补)