2020.5.30 解题报告

2020.5.30


\[\text{30分钟,D题做不出来,我当场就把这个显示屏,吃掉!} \]

\[\text{By:Rushingblock} \]


答题情况

总成绩 : 280 , 排名 : 94 / 1097
T1 : 100 T2 : 100 T3 : 80 T4:0

各题目分析

题目 1 :
预估成绩 : 100 实际成绩 : 100 考试用时 : 2:00 ~ 2:10

签到水题。

题目 2 :
预估成绩 : 100 实际成绩 : 100 考试用时 : 2:10 ~ 3:00

黄题难度。
手生了,应该能在30min之内调出来的。

题目 3 :
预估成绩 : 80 实际成绩 : 80 考试用时 : 3:10 ~ 5:30

先写了暴力,之后死推性质,拿了80。

题目 3 :
预估成绩 : 10 实际成绩 : 0 考试用时 : 5:30 ~ 6:00

还有半个小时rush了一波。
rua过样例电脑卡了没交上。


题目解析

T1

输出 \(2 \times \mid O \mid - 1\) 即可。
注意ull不溢出。


T2

先 dfs 判断给出图形是否全部由链组成。
满足下列条件之一的联通块即为链。

  • 大小为1。
  • 两端点只有一个相邻的位置,其他位置都恰好有两个相邻位置

若图中出现非链的联通块,则该图不合法。

dfs找链的个数。
对于一条链,可以直接将其转化为做一个数列。现在需要往数列上填数,使相邻的数互不相同。
则除第一个位置填k种外,其他位置均填k-1种,一条链的贡献即为 \(k \times (l - 1) ^ {k - 1}\)


T3

什么样子的分数可以表示为十进制有限小数?
约分后,分母只含 2, 5 两种因子的分数可以。

40 pts:

直接 \(n ^ 2\) 两重循环,暴力模拟即可。

80 pts:

观察定义,先不考虑分子分母约分。
发现 当分母只含2, 5 两种因子时,分子取何值均满足条件。
考虑反向约分,使分母分子都乘上一个数,即为如下形式:

\[\dfrac{ac}{bc} \]

尝试先枚举 c。
那么,b 的取值依然是 [1, ⌊𝑛/𝑐⌋] 的任何数,而 𝑎 的取值就变为了 [1, ⌊𝑛/𝑐⌋] 中任何只含 2, 5 两种因子的数。
发现,𝑎 的取值的个数随着 𝑐 的增大而单调减小,所以可以在总共 𝑂(𝑛) 的时间中计算。
也就是,对于每个 𝑐,记合法的 𝑎 的个数为 𝑑,则它对答案的贡献为 \(𝑑\times ⌊𝑛/𝑐⌋\)
时间复杂度依然是 \(𝑂(𝑛)\)

100 pts:

使用整除分块 + 容斥原理优化上述过程。


T4

10pts

爆搜枚举走过的路径,模拟运动状况。
答案比较小,可乱搞过掉。

100 pts

我们可以想到,敌人有很多是重复的,所以每一个位置上只留一个敌人即可。

然后,我们可以贪心的想:走到一个位置以后,等着别人来送死。

如何求出这个位置?
显然该位置在树的直径的中点处。


代码实现

T1 :

考场代码(正解)

//
/*
By:Luckyblock
*/
#include <cstdio>
#include <ctype.h>
#include <iostream>
#define min std::min
#define max std::max
#define ll long long
#define ull unsigned long long
//=============================================================
ll O;
ull O1;
//=============================================================
inline int read() {
	int f = 1, w = 0; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
	for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
	return f * w;
}
//=============================================================
int main() {
  std :: cin >> O;
  if (O <= 0) {
    printf("0"); 
    return 0;
  }
  O1 = O;
  std :: cout << (O1 - 1) * 2 + 1;
	return 0;
}


T2:

考场代码(正解)

//
/*
By:Luckyblock
*/
#include <cstdio>
#include <ctype.h>
#include <cstring>
#include <algorithm>
#define min std::min
#define max std::max
#define ll long long
const int kMaxn = 1010;
const int mod = 998244353;
const int ex[5] = {- 1, 0, 1, 0};
const int ey[5] = {0, - 1,  0, 1};
//=============================================================
ll n, m, k, ans = 1;
int line_num, num1, num2, size, num[kMaxn][kMaxn], lth[kMaxn << 6];
char map[kMaxn][kMaxn];
bool vis[kMaxn][kMaxn];
//=============================================================
inline ll read() {
	ll f = 1, w = 0; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
	for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
	return f * w;
}
void Dfs(int x, int y) {
  size ++; 
  vis[x][y] = true;
  for (int i = 0; i < 4; i ++) {
    if (map[x + ex[i]][y + ey[i]] == 'O') {
      num[x][y] ++;
      if (! vis[x + ex[i]][y + ey[i]]) {
        Dfs(x + ex[i], y + ey[i]); 
      }
    }
  }
  if (num[x][y] > 2) num2 ++;
  if (num[x][y] == 1) num1 ++;
}
bool RoomJudge() {
  for (int i = 1; i <= n; ++ i) {
    for (int j = 1; j <= m; ++ j) {
      if (map[i][j] == 'O' && ! vis[i][j]) {
        num1 = size = num2 = 0;
        Dfs(i, j);
        lth[++ line_num] = size;
        if (size == 1) num1 += 2;
        if (num1 != 2 || num2) return true;
      }
    }
  }
  return false;
}
ll qpow(ll x, ll y) {
  ll ret = 1;
  while (y) {
    if (y & 1) ret = ret * x % mod;
    y >>= 1, x = x * x % mod;
  }
  return ret;
}
//=============================================================
int main() {
  n = read(), m = read(), k = read();
  for (int i = 1; i <= n; ++ i) {
    scanf("%s", map[i] + 1);
  }
  if (RoomJudge()) {
    printf("0\n");
    return 0;
  }
  for (int i = 1; i <= line_num; i ++) {
    ans *= k * qpow(k - 1, lth[i] - 1) % mod;
    ans %= mod;
  }
  printf("%lld\n", ans);
}
/*
1 1 2
O
*/ 

T3:

考场代码

//
/*
By:Luckyblock
*/
#include <map>
#include <queue>
#include <cstdio>
#include <ctype.h>
#include <algorithm>
#define min std::min
#define max std::max
#define ll long long
const int kMaxn = 1e7 + 10;
//=============================================================
ll n, num1, num2, ans;
bool flag[kMaxn]; 
int q1[kMaxn], q2[kMaxn], sum[kMaxn];
//=============================================================
inline ll read() {
	ll f = 1, w = 0; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
	for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
	return f * w;
}
//=============================================================
int main() {
  n = read();
  flag[2] = flag[5] = true;
  q1[++ num1] = 1;
  if (n >= 2) q1[++ num1] = 2;
  if (n >= 5) q1[++ num1] = 5;
  for (int i = 2; i <= num1; ++ i) {
    int top = q1[i];
    if (! flag[top * 2] && top * 2 <= n) {
      q1[++ num1] = top * 2;
      flag[top * 2] = true;
    }
    if (! flag[top * 5] && top * 5 <= n) {
      q1[++ num1] = top * 5;
      flag[top * 5] = true;
    }
  }
  
  sum[0] = n;
  for (int i = 2; i <= n; ++ i) {
    if (i % 2 == 0 || i % 5 == 0) continue ;
    q2[++ num2] = i;
    sum[num2] += sum[num2 - 1] + (n / i);
  }

  std :: sort(q1 + 1, q1 + num1 + 1);
  for (int i = 1, j = num2; i <= num1; i ++) {
    while (q1[i] * q2[j] > n) j --;
    ans += sum[j];
  }
  printf("%lld", ans);
	return 0;
}

T4

考场代码

//
/*
By:Luckyblock
*/
#include <cstdio>
#include <ctype.h>
#include <cstring>
#include <algorithm>
const int kMaxn = 30;
//=============================================================
struct Edge {
  int u, v, ne;
} e[kMaxn << 1];
int edge_num, head[kMaxn];
int n, m, k, x, ans = 114514, dep[kMaxn], fa[kMaxn];
int rest, pos[kMaxn], tmp[kMaxn];
bool kill[kMaxn], vis[kMaxn];
//=============================================================
inline int read() {
	int f = 1, w = 0; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
	for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
	return f * w;
}
void AddEdge(int u, int v) {
  e[++ edge_num].u = u, e[edge_num].v = v;
  e[edge_num].ne = head[u], head[u] = edge_num;
}
void Dfs1(int u) {
  for (int i = head[u]; i; i = e[i].ne) {
    if (! dep[e[i].v]) {
      dep[e[i].v] = dep[u] + 1;
      fa[e[i].v] = u;
      Dfs1(e[i].v); 
    }
  }
}
void Dfs(int time) {
  if (time > ans) return ;
  if (! rest) {
    ans = std :: min (time, ans);
    return ;
  }

  int cnt = 0;
  for (int i = 1; i <= m; ++ i) {
    if (! kill[i] && dep[pos[i]] - 1 <= k) {
      rest --;
      kill[i] = true;
      tmp[++ cnt] = i;
    }
  }

  for (int i = head[x]; i; i = e[i].ne) {
    memset(dep, 0, sizeof (dep));
    x = e[i].v;
    dep[e[i].v] = 1;
    Dfs1(e[i].v);
    for (int j = 1; j <= m; ++ j) {
      pos[j] = fa[pos[j]];
    }
    Dfs(time + 1);
  }
  
  for (int i = 1; i <= cnt; ++ i) {
    rest ++;
    kill[tmp[i]] = false;
  }
}
//=============================================================
int main() {
  n = read();
  for (int i = 1; i < n; ++ i) {
    int u = read(), v = read();
    AddEdge(u, v), AddEdge(v, u);
  }
  rest = m = read();
  for (int i = 1; i <= m; i ++) pos[i] = read();
  k = read(), x = read();
  dep[x] = 1;
  Dfs1(x);
  Dfs(0);
  printf("%d\n", ans);
	return 0;
}
posted @ 2020-05-30 21:31  Luckyblock  阅读(210)  评论(0编辑  收藏  举报