Edu Round#83(div2)

Edu Round#83(div2)

昨天晚上又没有参加 \(CF\) ,已经好久没有打了。决定今天老老实实补提

\(A,B,C\) 好像比较水。

A 、Two Regular Polygons

for _ in range(int(input())):
    n,m = map(int,input().split())
    if n % m == 0:
        print("YES")
    else:
        print("NO")

B、Bogosort

for _ in range(int(input())):
    n = int(input())
    L = list(map(int,input().split()))
    L.sort()
    print(*L[::-1])

C、 Adding Powers

for _ in range(int(input())):
    n,k = map(int,input().split())
    L = list(map(int,input().split()))
    
    ok = True
    bit = [0] * 100

    for x in L:
        while x > 0:
            base = 1
            p = 0
            while base * k <= x:
                base *= k
                p += 1
            
            bit[p] += 1
            x -= base
    for i in range(100):
        if bit[i] > 1:
            ok = False
            break
    if ok:
        print("YES")
    else:
        print("NO")

D、 Count the Arrays

题意:

给定 \(n,m\) 问,满足如下条件的数组的个数,对 \(998244353\) 取模

  • 数组长度是 \(n\)
  • 每个元素在 \([1,m]\)
  • 每个组数中有且仅有一对元素的值相等
  • 存在一个下标 \(p\) ,使得区间 \([1,p]\) 严格递增,\([p,n]\) 严格递减

思路:

  • 首先从 \(m\) 个数中选出 \(n-1\) 个不同的数,选择方法有 \(C_{\ m}^{\ n-1}\)
  • 选一个数复制一份,不能选最大的,有 \(n-2\) 个选择
  • 而对于剩下的 \(n-3\) 个数,(除去最大的和一对),他们有两种选择,可以在最大数的左边或则右边,这里有 \(2^{n-3}\) 种选法

\[ Ans = C_{\ m}^{\ n-1} \cdot (n-2) \cdot 2^{n-3} \]
代码:

这个线性推阶乘和逆元的式子。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll mod = 998244353;

ll qpow(ll a, ll n) {
    ll ans = 1;

    while (n) {
        if (n & 1ll) {
            ans = ans * a % mod;
        }
        a = 1ll * a * a % mod;
        n >>= 1ll;
    }

    return ans;
}

ll Get_Inv(ll n) {
    return qpow(n, mod - 2);
}

const ll maxn = 2e5 + 10;
ll fac[maxn], inv[maxn];

void init() {
    fac[0] = 1;
    for (ll i = 1; i < maxn; i++) {
        fac[i] = 1ll*fac[i - 1] * i % mod;
    }

    inv[maxn - 1] = Get_Inv(fac[maxn - 1]);

    for (ll i = maxn - 2; i >= 0; i--) {
        inv[i] = 1ll*inv[i + 1] * (i + 1) % mod;
    }
}

ll C(ll m, ll n) { // $C^m_n$
    if (n < m || n < 0) return 0;
    return 1ll*fac[n] * inv[n - m] % mod * inv[m] % mod;
}

ll n, m;

int main() {
    cin >> n >> m;
    init();
    if (n == 2) {
        cout << 0 << endl;
        return 0;
    }
    ll ans = C(n - 1, m) * qpow(2, n - 3) % mod * (n - 2ll) % mod;
    cout << ans << endl;
}

E、 Array Shrinking

题意:

有一个序列,你可以选择一对相邻的数字 \(a_i=a_{i+1}\),然后将这两个数字换为\(a_i+1\)

问最后最少能留下多少个数字。

\(CF\) 上看了别人的代码,看了一个感觉特别好理解。

这道题应该是区间Dp

#include<bits/stdc++.h>
using namespace std;

const int maxn = 550;

int p[maxn][maxn];// p[i][j] 表示区间 [i,j] 能否合成一个数
int dp[maxn];

int stk[maxn];
int top;

int A[maxn];

int main(){
    int n;scanf("%d",&n);

    for(int i = 1;i <= n;i++){
        scanf("%d",A+i);
    }

    for(int l = 1;l <= n;l++){
        top = 0;
        for(int r = l;r <= n;r++){
            stk[++top] = A[r];
            while(top > 1){
                if(stk[top] == stk[top-1]){
                    top--;
                    stk[top]++;
                }
                else{
                    break;
                }
            }
            if(top == 1){
                p[l][r] = 1;
            }
        }
    }

    for(int i = 1;i <= n;i++){
        dp[i] = i;
        for(int j = 1;j <= i;j++){
            if(p[j][i]){
                dp[i] = min(dp[i],dp[j-1] + 1);
            }
        }
    }
    printf("%d\n",dp[n]);
}

猜你喜欢

转载自www.cnblogs.com/sduwh/p/12456577.html