2023杭电多校第一场补题报告 1002 1005 1009 1012

2023杭电多校第一场补题报告 1002 1005 1009 1012

1002 City Upgrading (hdu.edu.cn)

思路

直接上树形dp,比较麻烦的是需要考虑父节点的影响,其他比较模板。

代码

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second

using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n;
int a[N];

vector<int> g[N];
int sc[N];
int dp[N][10];  // dp[i][0] 0被父亲覆盖,1被儿子覆盖,2被自己覆盖
void dfs(int u, int f) {
  dp[u][0] = 0;
  dp[u][1] = 0;
  dp[u][2] = sc[u];
  int ok = 0;
  for (auto v : g[u]) {
    if (v != f) {
      dfs(v, u);
      dp[u][0] += min(dp[v][1], dp[v][2]);
      dp[u][1] += min(dp[v][1], dp[v][2]);
      // cout << "###" << dp[v][1] << " " << dp[v][2] << endl;
      if (dp[v][2] <= dp[v][1]) ok = 1;
      dp[u][2] += min({dp[v][0], dp[v][1], dp[v][2]});
    }
  }
  // cout << dp[2][1] << endl;
  if (ok == 0) {
    int mi = INF;
    int id = -1;
    for (auto v : g[u]) {
      if (v != f) {
        int d = dp[v][2] - dp[v][1];
        if (d < mi) {
          mi = d;
          id = v;
        }
      }
    }
    dp[u][1] += mi;
  }
}
void solve() {
  int n;
  cin >> n;
  for (int i = 1; i <= n; i++) {
    g[i].clear();
    dp[i][0] = dp[i][1] = dp[i][2] = INF;
    cin >> sc[i];
  }
  for (int i = 0; i < n - 1; i++) {
    int x, y;
    cin >> x >> y;
    g[x].push_back(y);
    g[y].push_back(x);
  }
  dfs(1, 0);
  // for(int i = 1;i <= n;i++){
  // cout << dp[i][0] << " " << dp[i][1] << " " << dp[i][2] << endl;
  // }
  cout << min(dp[1][1], dp[1][2]) << "\n";
}

signed main() {
  IOS;
  int t = 1;
  cin >> t;
  for (int i = 1; i <= t; i++) {
    solve();
  }
}

1005 Cyclically Isomorphic (hdu.edu.cn)

思路

因为所有字符串在循环意义上的字典序最小应该是一样的,所以预处理出来所有字符串的字典序最小排列,然后直接对比即可。

代码

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second

using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n, m, d;
int a[N];

void solve() {
  cin >> n >> m;
  vector<string> st(n + 10);
  for (int i = 1; i <= n; i++) {
    string s;
    cin >> s;
    string tmp = s;
    for (int j = 0; j < m; j++) {
      s = s + s[0];
      s.erase(s.begin());
      tmp = min(tmp, s);
    }
    st[i] = tmp;
  }
  int q;
  cin >> q;
  while (q--) {
    int x, y;
    cin >> x >> y;
    if (st[x] == st[y])
      cout << "Yes\n";
    else
      cout << "No\n";
  }
}

signed main() {
  IOS;
  int t = 1;
  cin >> t;
  for (int i = 1; i <= t; i++) {
    solve();
  }
}

1009 Assertion (hdu.edu.cn)

思路

直接抽屉原理,但是貌似编译器原因用除法会T,改成乘法ac了。

代码

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second

using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n, m, d;
int a[N];

void solve() {
  cin >> n >> m >> d;
  if (d == 0) {
    cout << "Yes\n";
    return;
  }
  if ((d - 1) * n + 1 <= m)
    cout << "Yes\n";
  else
    cout << "No\n";
}

signed main() {
  IOS;
  int t = 1;
  cin >> t;
  for (int i = 1; i <= t; i++) {
    solve();
  }
}

1012 Play on Tree (hdu.edu.cn)

思路

首先求出来sg函数(比较典就是所有子节点sg函数+1的异或和),然后再换根dfs跑一遍计数即可。

代码

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>  //
#include <fstream>
#include <iostream>
#include <map>    //
#include <queue>  //队列
#include <set>    //
#include <stack>  //栈
#include <string>
#include <vector>  //向量
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second

using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n;
int a[N];

int qpow(int a, int b) {
  int ans = 1, base = a;
  while (b) {
    if (b & 1) ans = ans * base % mod;
    base = base * base % mod;
    b >>= 1;
  }
  return ans % mod;
}
int sg[N], sg2[N];
vector<int> g[N];

void dfs(int u, int f) {
  sg[u] = 0;
  for (auto v : g[u])
    if (v != f) {
      dfs(v, u);
      sg[u] ^= (sg[v] + 1);
    }
}
int ans = 0;
void dfs2(int u, int f) {
  for (int v : g[u]) {
    if (v != f) {
      sg2[v] = sg[v] ^ ((sg2[u] ^ (sg[v] + 1)) + 1);
      dfs2(v, u);
    }
  }
}
void solve() {
  int n;
  cin >> n;
  ans = 0;
  for (int i = 1; i <= n; i++) {
    g[i].clear();
    sg[i] = 0;
  }
  for (int i = 1; i < n; i++) {
    int u, v;
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  dfs(1, 0);
  sg2[1] = sg[1];
  dfs2(1, 0);
  for (int i = 1; i <= n; i++)
    if (sg2[i]) ans++;
  cout << ans * qpow(n, mod - 2) % mod << "\n";
}

signed main() {
  IOS;
  int t = 1;
  cin >> t;
  for (int i = 1; i <= t; i++) {
    solve();
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值