2020 HDU Multi-University Training Contest 5(部分)

6814 Tetrahedron

用任何方法,只要计算出 1 h 2 = 1 a 2 + 1 b 2 + 1 c 2 \frac{1}{h^2}=\frac{1}{a^2}+\frac{1}{b^2}+\frac{1}{c^2} h21=a21+b21+c21即可

#include<cstdio>
using namespace std;
typedef long long ll;
const ll p = 998244353;
const ll maxn = 6e6;
int T;
ll n, Inv[maxn + 1], a[maxn + 1];
ll ksm(ll a, ll b) {
    ll res = 1;
    while (b){
        if (b & 1)res = (res * a) % p;
        a = (a * a) % p;
        b >>= 1;
    }
    return res;
}
ll inv(ll x) { return ksm(x, p - 2); }
void init() {
    for (ll i = 1; i <= maxn; i++)
        Inv[i] = inv(i);
    for (int i = 1; i <= maxn; i++)
        a[i] = (a[i - 1] + (Inv[i] * Inv[i]) % p) % p;
}
int main(void) {
    init();
    scanf("%d", &T);
    while (T--) {
        scanf("%lld", &n);
        printf("%lld\n", a[n] * Inv[n] % p * 3 % p);
    }
    return 0;
}

6816 Boring Game

模拟如图所示的过程,将每次折叠重新一次次打开来

在这里插入图片描述

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxp = 2 * 200 * (1 << 10) + 5;
int T, n, k, p[maxp];
vector<int>a[maxp];
int main(void) {
	scanf("%d", &T);
	while (T--) {
		scanf("%d%d", &n, &k);
		int len = 2 * n * (1 << k);
		int m = 1 << k;
		for (int i = 1; i <= m; i++)a[i].clear();
		for (int i = 1; i <= len; i++) {
			scanf("%d", &p[i]);
			a[m].push_back(p[i]);
		}
		reverse(a[m].begin(), a[m].end());
		
		for (int t = 0; t < k; t++) 
			for (int i = m - (1 << t) + 1, j = i - 1; i <= m; i++, j--) {
				int size = (int)(a[i].size()) / 2;
				while (size--) {
					a[j].push_back(a[i].back());
					a[i].pop_back();
				}			
			}

		int dep = a[m].size();
		for (int d = 1; d <= dep; d++) {
			for (int i = 1; i <= m; i++) {
				printf("%d", a[i].back()); a[i].pop_back();
				if (d == dep && i == m && a[i].size() == 0)printf("\n");
				else printf(" ");
			}
		}
	}
	return 0;
}

6822 Paperfolding

折叠完后,在纸的中心画个点,然后按折叠的方式来把纸摊开,最后恢复成开始的样子,看纸面上的点,横竖相连成网格,则划分的区域即为答案。显然左右和上下是等效的,则只看左和上即可,左折x次,横向展开后有2^x个点,上折n-x次,竖向有2^(n-x)个点,然后画画图,可看出n次操作取x个为左折,剩下为上折,答案为(2^x-1)*(2^(n-x)-1)+2*(2^x-1)+2*(2^(n-x)-1)+4(x=0,1,…,n),记得乘以组合数,最后除以2^n
推推公式即可得出答案为2^n+1+2*(3/2)^n

#include<cstdio>
using namespace std;
typedef long long ll;
const ll p = 998244353;
int T;
ll n;
ll ksm(ll a, ll b) {
    ll res = 1;
    while (b){
        if (b & 1)res = (res * a) % p;
        a = (a * a) % p;
        b >>= 1;
    }
    return res;
}
ll inv(ll x) { return ksm(x, p - 2); }
int main(void) {
    scanf("%d", &T);
    while (T--) {
        scanf("%lld", &n);
        printf("%lld\n", (ksm(2, n) + 1 + 2 * ksm(3LL * inv(2) % p, n)) % p);
    }
    return 0;
}

6825 Set1

看下题解就懂,但是答案要再除以((2*i-n-1)/2)!,因为取2取2…的操作,其实每次取出来应该有固定位置,因为操作1取的是当前的最小值,取出x,y时,x为操作1取值然后再取y,则必有x<y,也必有在特定的位置才能取到x值。
在这里插入图片描述

#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn = 5e6;
const ll p = 998244353;
int T, n;
ll f[maxn + 1], pow2[maxn + 1], inv[maxn + 1], cnt[maxn + 1];
ll ksm(ll a, ll b) {
    ll res = 1;
    while (b) {
        if (b & 1)res = (res * a) % p;
        a = a * a % p;
        b >>= 1;
    }
    return res % p;
}
ll Inv(ll x) {
    return ksm(x, p - 2);
}
ll Cmn(ll m, ll n) {//m取n
    if (n == 0)return 1;
    return f[m] * inv[m - n] % p * inv[n] % p;
}
int main(void) {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    f[0] = f[1] = pow2[0] = 1; pow2[1] = 2;
    for (int i = 2; i <= maxn; i++) {
        f[i] = i * f[i - 1] % p;
        pow2[i] = pow2[i - 1] * 2 % p;
    }
    inv[0] = inv[1] = 1; inv[maxn - 1] = Inv(f[maxn - 1]);
    for (int i = maxn - 2; i > 1; i--) {
        inv[i] = (i + 1) * inv[i + 1] % p;
    }
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        int len = (n - 1) / 2;
        for (int i = 1; i <= len; i++)cnt[i] = 0;
        for (int i = len + 1; i <= n; i++) 
            cnt[i] = Cmn(i - 1, n - i) * f[n - i] % p * f[2 * i - n - 1] % p * Inv(pow2[(2 * i - n - 1) / 2]) % p * Inv(f[(2 * i - n - 1) / 2]) % p;
        ll sum = 0;
        for (int i = 1; i <= n; i++)
            sum = (sum + cnt[i]) % p;
        ll invSum = Inv(sum);
        for (int i = 1; i <= n; i++) {
            printf("%lld%c", cnt[i] * invSum % p, i == n ? '\n' : ' ');
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JILIN.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值