Loading

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]);
}
posted @ 2020-03-10 16:36  —O0oO-  阅读(128)  评论(0编辑  收藏  举报