2025-11-20

CF

Problem - 982C - Codeforces(搜索)(dfs)

找最大删除边数,使得每一棵树的顶点数都为偶数

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=1e5+10;
vector<int>e[N];
int ans[N];

int dfs(int u,int fa){
    for (int i = 0; i < e[u].size();i++){
        int v = e[u][i];
        if(v==fa)
            continue;
        ans[u] += dfs(v, u);
    }
    ans[u]++;
    return ans[u];
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for (int i = 0; i < n - 1;i++){
        int u, v;
        cin >> u >> v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    if(n%2){
        cout << -1 << endl;
        return 0;
    }
    dfs(1,0);
    int cnt = 0;
    for (int i = 1; i <= n;i++){
        if(ans[i]%2==0){
            cnt++;
        }
    }
    cout << cnt - 1 << endl;
}

Problem - 545C - Codeforces(贪心)(1500)

要让砍的树最多,则

  • 第1棵往左,最后一棵往右
  • 如果能往左,就往左
  • 如果不能往左,能往右,就往右倒
    为什么呢,因为如果第i棵树不能往左,不砍的话,就少砍一棵树,但是,如果往右的话,即使影响到下一棵树,也只是少砍一棵树,所以贪心最优
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=1e5+10;
int x[N], h[N];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for (int i = 0; i < n;i++){
        cin >> x[i] >> h[i];
    }
    int t = 0;
    for (int i = 1; i < n-1;i++)
    {
        if(x[i]-h[i]>x[i-1])
            t++;
        else if(x[i]+h[i]<x[i+1]){
            t++;
            x[i] += h[i];
        }
    }
    if(n==1){
        cout << 1 << endl;
    }
    else{
        cout << t + 2 << endl;
    }
}

Problem - 1081C - Codeforces(数学)(1500)(逆元)

要使k个砖块与左边颜色不同,用隔板法,把砖块分成k+1份,每份涂上与旁边不同的颜色即可,所以公式为:

\[C_{n-1}^k \cdot m(m-1)^k \]

[!warning]
qmi如果用LL,就全改LL
取模尽量多取

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=2010;
LL f[N], inv[N];
LL C(int n,int m){
    return f[n] * inv[m] % mod * inv[n - m] % mod;
}
LL qmi(LL a,LL b,LL p)
{
    LL res=1;
    while(b)
    {
        if(b&1)
            res = res * a % p;
        a=a*a%p;
        b >>= 1;
    }
    return res;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    f[0] = f[1] = inv[0] = inv[1] = 1;
    for (int i = 2; i <= n; i++)
    { // 求阶乘和单个数逆元
        f[i] = f[i - 1] * i % mod;
        inv[i] = mod - (mod / i) * inv[mod % i] % mod;
    }
    for (int i = 1; i <= n; i++)
    { // 求阶乘逆元
        inv[i] = inv[i - 1] * inv[i] % mod;
    }
    cout << C(n - 1, k) %mod *m%mod * qmi(m - 1, k, mod)%mod << endl;
}

dp解法
dp[i][j]表示前i个砖由j块满足题意
dp[i][j]dp[i-1][j]dp[i-1][j-1]*(m-1)(即第i块可以放m-1种颜色)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=2010;
LL dp[N][N];
int n, m, k;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m >> k;
    for (int i = 1; i <= n;i++){
        dp[i][0] = m;
        for (int j = 1; j < min(k + 1, i);j++){
            dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] * (m - 1) % mod;
            dp[i][j] %= mod;
        }
    }
    cout << dp[n][k] << endl;
}
posted @ 2025-11-21 19:08  Seren_blingbling  阅读(3)  评论(0)    收藏  举报