12.28 CW 模拟赛 赛时记录
前言
还是只管考试的策略, 别想其他的
每个题控制用时, 根据时间选择策略, 冷静
看题
完蛋了是
#
怎么办, 像是很典的题但是我多半做不出来
别人做过容斥的肯定会, 但是我就不一样了
#
好像也不会做
#
基环树上的
#
有点像一位故人出的题
思路#
题意非常清楚, 就是用
你发现
有倍数条件的同时还有数字的约束, 不太好做
你发现如果
考虑引入
好吧我不会了, 打个暴力看下给了多少
代码#
#include <bits/stdc++.h>
#define int long long
int X, A, B;
bool S[10];
int st; // 开始枚举的位置
int ans = 0;
bool check(int x) {
while (x) {
if (!S[x % 10]) return false; x /= 10; }
return true;
}
signed main()
{
scanf("%lld %lld %lld", &X, &A, &B);
std::string a; std::cin >> a; for (int i = 0; i < a.length(); i++) S[a[i] - '0'] = true;
st = (A % X) ? A / X + 1 : A / X; st *= X;
for (int i = st; i <= B; i += X) {
if (check(i)) ans++;
if (clock() > 990) {
printf("%lld", ans); return 0; }
}
printf("%lld", ans);
return 0;
}
思路#
这个题说不定比
好像明显有点畏难, 但是他一点提示没有不敢做
首先因为忘了欧氏距离是什么, 先玩一下样例
好的欧氏距离是, 对于两个点
转化题意, 对于
容易发现的是, 如果你要选择一些确定的点, 使其在同一连通块下, 那么你是可以求出最小阈值
现在问题转化成了, 如何在一个图的连通块中, 判断是否可能有一些点的点权之和为
所以我们初步可以有一个暴力, 首先实数二分
好像还没说可行性
令
显然有转移
其中
总结一下, 首先实数二分当前阈值
总复杂度
写的时候遇到了问题, 不能用
实现#
框架#
实数二分,
代码#
/*相信 O2 优化*/
#include <bits/stdc++.h>
// #define FILE_IO
#define int long long
const int MAXN = 5e4 + 20;
const double eps = 1e-4;
const int MAXVAL = 40;
#define dist(a, b) sqrt((double)(p[a].x - p[b].x) * (p[a].x - p[b].x) + (p[a].y - p[b].y) * (p[a].y - p[b].y))
int n, K;
struct node {
int x, y, k;
} p[MAXN];
int be[MAXN], cnt;
/*辅助处理连通块的 bfs*/
void bfs(int now, int divnum, double C) {
be[now] = divnum;
for (int i = 1; i <= n; i++) {
if (be[i] || dist(now, i) - C > eps) continue;
bfs(i, divnum, C);
}
}
std::vector<int> Div[MAXN];
/*在当前阈值情况下处理连通块*/
void divide(double C) {
memset(Div, 0, sizeof(Div));
for (int i = 1; i <= n; i++) be[i] = 0; cnt = 0;
for (int i = 1; i <= n; i++) if (!be[i]) bfs(i, ++cnt, C);
for (int i = 1; i <= n; i++) Div[be[i]].push_back(i);
}
/*检查阈值是否合法*/
bool check(double C) {
divide(C);
/*在当前连通块中处理可行性 dp*/
for (int k = 1; k <= cnt; k++) {
bool flag = false; // 是否可以整除
int now = 0, nxt = 1;
int dp[2][MAXVAL][2]; memset(dp, false, sizeof(dp)); dp[now][0][0] = true;
for (int i = 0; i < Div[k].size(); i++) {
std::swap(now, nxt); memset(dp[now], false, sizeof(dp[now]));
int nowk = p[Div[k][i]].k;
for (int j = 0; j < 40; j++) {
dp[now][j][0] |= dp[nxt][j][0];
dp[now][j][1] |= dp[nxt][j][1];
dp[now][(j + nowk) % K][1] |= dp[nxt][j][0];
dp[now][(j + nowk) % K][1] |= dp[nxt][j][1];
}
if (dp[now][0][1]) flag = true;
}
if (flag) return true;
}
return false;
}
/*二分答案*/
double binsearch() {
double left = 0.0, right = 100000000.0;
while (right - left > eps) {
double mid = left + (right - left) / 2.0;
if (check(mid)) right = mid;
else left = mid;
}
return left;
}
signed main()
{
#ifdef FILE_IO
freopen("connect_ex1.in", "r", stdin);
freopen("connect_ex1.out", "w", stdout);
#endif
scanf("%lld %lld", &n, &K);
for (int i = 1; i <= n; i++) scanf("%lld %lld %lld", &p[i].x, &p[i].y, &p[i].k);
// std::cout << check(1.3);
double ans = binsearch();
printf("%.3f", ans);
return 0;
}
看起来很板的基环树上
看起来也不能再写点什么了, 那就推推这个
套路的, 先考虑单棵树上怎么操作
令
对于叶子节点的初始化是显然的, 考虑树形
显然的, 这样子会漏统计一种情况 : 子树的根节点本来是没有关键点与之相连的, 但是在
这个时候我们朴素的考虑往上加一维表示这个子树是否有关键点与之相连, 反正如果隔了一层一定不成立, 所以这样做是有正确性的
考虑令
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】