2020 杭电多校第五场(Multi-University Training Contest 5)

目录

Tetrahedron

Paperfolding

Boring Game


Tetrahedron

2020 杭电多校第五场(Multi-University Training Contest 5)_第1张图片

 大致题意:

给你一个四面体(三条棱之间分别呈90度),然后给出三条棱 a , b , c 的长度的范围:随机取(1,n)之间的任意一个整数;求四面体的高h:\frac{1}{h^2} 的期望值

思路:

首先要找出来  a, b, c 和 \frac{1}{h^2}之间的关系;(做题的时候随便找的公式):\frac{1}{h^2}=\frac{1}{a^2}+\frac{1}{b^2}+\frac{1}{c^2}

官方题解给的证明:

2020 杭电多校第五场(Multi-University Training Contest 5)_第2张图片

2020 杭电多校第五场(Multi-University Training Contest 5)_第3张图片

 

#include  
using namespace std;
typedef long long ll;
const int N=6*1e6+10;
const int mod=998244353;
ll a[N];
ll inv[N];
ll qmi(ll m, int k, int p)
{
    ll res = 1 % p, t = m;
    while (k)
    {
        if (k&1) res = res * t % p;
        t = t * t % p;
        k >>= 1;
    }
    return res;
}
int main()
{
    int t;
    scanf("%d",&t);
    inv[1]=1;
    for(int i=2;i<=N-10;i++) inv[i] = (mod-mod/i) * inv[mod%i] % mod;
    for(int i=1;i<=N-10;i++) a[i]=(a[i-1]+inv[i]*inv[i]%mod)%mod;
    while(t--)
    {
        ll n;
        scanf("%lld",&n);
        ll res=inv[n]%mod;
        printf("%d\n",n*n%mod*3%mod*a[n]%mod*res%mod*res%mod*res%mod);
    }
}

 

Paperfolding

2020 杭电多校第五场(Multi-University Training Contest 5)_第4张图片

大致题意:

就是 一张纸,可以上下对折,可以左右对折,然后对折的操作是随机的,求n次操作后,对纸张进行如图示剪开,然后求可以获得的纸片的数量的期望值是多少;

官方题解:

2020 杭电多校第五场(Multi-University Training Contest 5)_第5张图片

 然后按照公式计算即可,注意逆元的处理;

#include  
using namespace std;
typedef long long ll;
const int N=6*1e6+10;
const int mod=998244353;
ll a[N];
ll inv[N];
ll qmi(ll m, ll k, int p)
{
    ll res = 1 % p, t = m;
    while (k)
    {
        if (k&1) res = res * t % p;
        t = t * t % p;
        k >>= 1;
    }
    return res;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll n;
        scanf("%lld",&n);
        ll res=qmi(2,n,mod)%mod;
        cout <<(res+res*res%mod+2*qmi(3,n,mod)%mod)%mod*(qmi(res,mod-2,mod))%mod<

 

Boring Game

2020 杭电多校第五场(Multi-University Training Contest 5)_第6张图片

 思路:

就是n张纸,每次截取上半部分,然后倒置后放到剩余部分的左侧,模拟k次;

#include 
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e6 + 10;

int arr[N], tmp[N];
void solve(int n, int len)
{
    for (int i = 1; i <= n; i++) {
        tmp[i] = arr[i];
    }
    int cnt = 0;
    for (int i = n - len + 1; i > 0;i-=len){
        for (int j = i + len / 2 - 1; j >= i;j--){
            arr[++cnt] = tmp[j];
        }
    }
    for (int i = 1; i <= n; i += len) {
        for (int j = i + len / 2; j < i + len;j++){
            arr[++cnt] = tmp[j];
        }
    }
}
int main()
{
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, k;
        scanf("%d%d", &n, &k);
        int len = 2 * n * 1 << k;
        for (int i = 1; i <= len; i++) {
            scanf("%d", &arr[i]);
        }
        int now = len;
        for (int i = 1; i <= k; i++) {
            solve(len, now);
            now >>= 1;
        }
        int r = len / (1 << k);
        int c = 1 << k;
        int cnt = 0;
        for (int i = 1; i <= r; i++) {
            for (int j = 1; j <= c;j++){
                tmp[++cnt] = arr[i + (j - 1) * r];
            }
        }
        printf("%d", tmp[1]);
        for (int i = 2; i <= len;i++){
            printf(" %d", tmp[i]);
        }
        printf("\n");
    }
    return 0;
}

 

你可能感兴趣的:(基础算法——数论,#,逆元,思维)