NOIP提高组模拟赛26
A. LCIS
蓝书原题,CF10D 弱化版
首先直接把 LIS 和 LCS 合起来设计一个 DP .
设 \(dp_{i,j}\) 表示 \(A_{1\dots i}\) 和 \(B_{1\dots j}\) 的以 \(B_j\) 结尾的 LCIS,则:
\]
这样是 \(O(n^3)\) 的,肯定过不去(UPD. Eafoo 说能过)
然而因为 \(A_i=B_j\),我们可以把上面那个带 max 的转移里 \(B_j\) 换成 \(A_i\),这样可以发现当 \(i\) 一定时 max 只增不减,于是用一个变量记录一下,这样就是 \(O(n^2)\) 的了 .
using namespace std;
typedef pair<int, int> pii;
const int N = 3456, INF = 0x3f3f3f3f;
typedef long long ll;
int n, a[N], b[N], dp[N][N];
int main()
{
scanf("%d", &n);
for (int i=1; i<=n; i++) scanf("%d", a+i);
for (int i=1; i<=n; i++) scanf("%d", b+i);
for (int i=1, val; i<=n; i++)
{
val = 1;
for (int j=1; j<=n; j++)
{
dp[i][j] = dp[i-1][j];
if (a[i] > b[j]) chkmax(val ,dp[i-1][j] + 1);
if (a[i] == b[j]) chkmax(dp[i][j], val);
}
}
int ans = 0;
for (int i=1; i<=n; i++) chkmax(ans, dp[n][i]);
printf("%d\n", ans);
return 0;
}
B. 物流运输
口胡大师,思维混乱人.jpg
代码写一会推翻一段写一会推翻一段,,,,
顺便提一下,这题是 BZOJ #1003,题号还挺小 XD
看来我的做法是完全有问题了 /ll(UPD. 我做法好像类似 link 应该还能抢救一下),下面复读一下正解:
首先处理出时刻 \(i\sim j\) 都可以走的最短路长度 \(dis_{i,j}\),可以 SPFA 暴力 .
然后 DP 即可,令 \(dp_i\) 表示到第 \(i\) 天的答案,枚举一个 \(j\) 然后换即可,转移方程:
\]
DP 部分 \(O(n^2)\) .
总时间复杂度最坏是 \(O(n^2me)\) 的,如果最短路用 Dijkstra 那么复杂度就是 \(O(n^2m\log e)\) .
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int N = 1111;
const ll INF = 0x3f3f3f3f3f3fll;
typedef long long ll;
struct dsu
{
int fa[N];
dsu(){reset();}
int get(int x){return x == fa[x] ? x : fa[x] = get(fa[x]);}
inline void merge(int x, int y){fa[get(x)] = get(y);}
inline void reset(){iota(fa, fa+N, 0);}
}D;
int n, m, k, e, d, deg[N];
bitset<N> bb[N];
ll dist[N][N];
vector<pii> g[N];
inline void addedge(int u, int v, int w){g[u].emplace_back(make_pair(v, w));}
inline void ade(int u, int v, int w){addedge(u, v, w); addedge(v, u, w);}
ll dis[N];
bool vis[N];
inline void spfa(bitset<N> cannot)
{
memset(vis, false, sizeof vis);
memset(dis, 0x3f, sizeof dis);
queue<int> q; vis[1] = true; dis[1] = 0; q.push(1);
while (!q.empty())
{
int u = q.front(); q.pop();
for (auto e : g[u])
{
int v = e.first, w = e.second;
if (cannot[v]) continue;
if (dis[v] > dis[u] + w){dis[v] = dis[u] + w; if (!vis[v]) q.push(v), vis[v] = true;}
} vis[u] = false;
}
}
inline void prework()
{
bitset<N> tmpb;
for (int i=1; i<=n; i++)
for (int j=i; j<=n; j++)
{
for (int k=1; k<=n; k++) tmpb[k] = 0;
for (int k=i; k<=j; k++) tmpb |= bb[k];
spfa(tmpb);
if (dis[m] == dis[0]) dist[i][j] = INF;
else dist[i][j] = dis[m];
}
}
ll dp[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("i.in", "r", stdin);
#endif
scanf("%d%d%d%d", &n, &m, &k, &e); // m 是点数 m 是点数 m 是点数 m 是点数 m 是点数
for (int i=0, u, v, w; i<e; i++) scanf("%d%d%d", &u, &v, &w), ade(u, v, w);
scanf("%d", &d);
for (int i=0, p, a, b; i<d; i++){scanf("%d%d%d", &p, &a, &b); for (int j=a; j<=b; j++) bb[j][p] = 1;}
prework();
for (int i=0; i<=n; i++) dp[i] = INF;
for (int i=1; i<=n; i++)
{
dp[i] = dist[1][i] * i;
for (int j=1; j<i; j++) chkmin(dp[i], dp[j] + dist[j+1][i] * (i - j) + k);
} printf("%lld\n", dp[n]);
return 0;
}
C. tree
这题好神啊,然而 Eafoo 场切了 .
考虑给每条白边都加上一个偏移量 \(k\)(\(k\) 可以是负的)
那么我们再算 MST 的话就肯定 \(k\) 大白边就少,\(k\) 小白边就多了 .
然后我们是要正好 \(need\) 条白边,于是我们二分这个 \(k\),每次暴力 Kruskal 算 MST 然后数白边数量和 \(need\) 比较就好了 .
时间复杂度 \(O(n\log m)\),附带一个二分的常数 .
然后还有两个小细节:
- 如果边的长度一样优先选白边(双关键字排序,典)
- 这个 \(need\) 不一定能取到,此时要取最小的大于 \(need\) 的答案 .
关于这个情况 2,例子贺一下 Eafoo 的:

浅色是白边,深色是黑边 .
如果 \(need=1\),注意到这个 \(k\) 不管取多少 MST 中的白边都是 \(0\) 或 \(2\)(不要说什么 MST 不唯一之类的话,情况 1 保证了白边优先)
这样肯定就是有黑白边边权相同的情况了,所以可以直接替换掉,具体实现的时候找到这种方案然后假装它有 \(need\) 条白边正常算即可 .
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int N = 54321, M = 123456;
int n, m, need, mst;
struct Edge
{
int u, v, w, col;
bool operator < (const Edge& rhs) const
{
if (w == rhs.w) return col < rhs.col; // 白边优先
return w < rhs.w;
}
}ed[M];
struct dsu
{
int fa[N];
dsu(){reset();}
int get(int x){return fa[x] == x ? x : fa[x] = get(fa[x]);}
inline void merge(int x, int y){fa[get(x)] = get(y);}
inline void reset(){iota(fa, fa+N, 0);}
}D;
inline int kruskal()
{
int white = 0; mst = 0;
sort(ed, ed+m); D.reset();
for (int i=0; i<m; i++)
{
int u = D.get(ed[i].u), v = D.get(ed[i].v), w = ed[i].w, col = ed[i].col;
if (u == v) continue;
D.merge(u, v);
white += !col; mst += w;
} return white;
}
inline bool check(int k)
{
for (int i=0; i<m; i++) if (!ed[i].col) ed[i].w += k;
int white = kruskal();
for (int i=0; i<m; i++) if (!ed[i].col) ed[i].w -= k;
return white >= need;
}
int main()
{
scanf("%d%d%d", &n, &m, &need);
for (int i=0; i<m; i++) scanf("%d%d%d%d", &ed[i].u, &ed[i].v, &ed[i].w, &ed[i].col), ++ed[i].u, ++ed[i].v;
int l = -200, r = 200, ans = -1;
while (l <= r)
{
int mid = (l + r) >> 1;
if (check(mid)){l = mid + 1; ans = mst - mid * need;}
else r = mid - 1;
} printf("%d\n", ans);
return 0;
}
D. 建造游乐园
正睿原题
显然题目等价于 \(n\) 点欧拉图个数乘上 \(\dbinom n2\) .
令 \(f_n\) 表示 \(i\) 个点的欧拉图数量,\(g_n\) 表示 \(n\) 个点度为偶数的无向图数量 .
众所周知图存在欧拉回路当且仅当没有奇点 .
于是考虑加一个点,容斥掉不连通的
如果原图存在一个欧拉子图,那么 \(i\) 必然要连另外一方面,因为要保持性质,\(i\) 必须连奇点,于是就不连通了(\(i\) 连所有奇点) .
\(g_n\) 显然等于 \(2^{\tbinom{n-1}2}\)(钦定 \(n-1\) 个点随便连,剩下那个点用来平衡奇度点),于是递推式就是
\]
DP,\(O(n^2)\) .
using namespace std;
typedef pair<int, int> pii;
const int N = 2222, INF = 0x3f3f3f3f, P = 1e9+7;
typedef long long ll;
int n;
ll C[N][N], f[N], g[N];
ll qpow(ll a, ll n)
{
ll ans = 1;
while (n)
{
if (n&1) ans = ans * a % P;
a = a * a % P; n >>= 1;
} return ans;
}
int main()
{
C[0][0] = 1;
for (int i=1; i<N; i++)
{
C[i][0] = 1;
for (int j=1; j<=i; j++) C[i][j] = (C[i-1][j] + C[i-1][j-1]) % P;
}
scanf("%d", &n);
for (int i=1; i<=n; i++) g[i] = qpow(2, C[i-1][2]);
for (int i=1; i<=n; i++)
{
f[i] = g[i];
for (int j=1; j<i; j++) f[i] = (f[i] - f[j] * g[i-j] % P * C[i-1][j-1] % P + P) % P;
} printf("%lld\n", f[n] * C[n][2] % P);
return 0;
}
下面说一下 \(O(n\log n)\) 做法 .
让我们快进到 DP .
zero4338 是一眼看穿了这题的做法的 .
首先一个关键点:度数都为偶数的图可以分成若干个欧拉图,于是欧拉图计数完全等价于连通图计数 .
考虑 exp 的组合意义,因为普通图可以划分成若干个连通图 , 所以普通图是连通图的 exp , 连通图就是普通图的 ln .
根据快进了的 DP 环节,我们知道连通图的方案数就是 \(g_n\) .
所以令 \(f_n\) 的 EGF 为 \(F(z)\),\(g_n\) 的 EGF 为 \(G(z)\),则
\]
\(G\) 可以线性预处理,一次多项式 \(\ln\) 求出 \(F\),\(O(n\log n)\) .
然而不得不谈的是模数是 \(10^9+7\),我们仔细探讨一下过程,发现这个是完全依赖于任意模数多项式乘法的,直接 MTT 即可,还是 \(O(n\log n)\) .
然而这个带标号欧拉图计数就是 OEIS A033678 .
NOIP提高组模拟赛26的更多相关文章
- 10-18 noip提高组模拟赛(codecomb)T1倍增[未填]
T1只想到了找环,> <倍增的思想没有学过,所以看题解看得雨里雾里的(最近真的打算学一下! 题目出的挺好的,觉得noip极有可能出现T1T2T3,所以在此mark 刚开始T1以为是模拟,还 ...
- 10-18 noip提高组模拟赛(codecomb)T2贪心
T2:找min:一直找最小的那个,直到a[i]-x+1小于0,就找次小的,以此类推: 求max,也是一样的,一直到最大的那个,直到次大的比之前最大的大,就找次大的: 这个模拟,可以用上priority ...
- HGOI20180815 (NOIP 提高组模拟赛 day2)
Day 2 rank 11 100+35+30=165 本题是一道数论题,求ax+by=c的正整数对(x,y) x>=0并且y>=0 先说下gcd: 求a,b公约数gcd(a,b) 如gc ...
- 【洛谷】NOIP提高组模拟赛Day2【动态开节点/树状数组】【双头链表模拟】
U41571 Agent2 题目背景 炎炎夏日还没有过去,Agent们没有一个想出去外面搞事情的.每当ENLIGHTENED总部组织活动时,人人都说有空,结果到了活动日,却一个接着一个咕咕咕了.只有不 ...
- 【洛谷】NOIP提高组模拟赛Day1【组合数学】【贪心+背包】【网络流判断是否满流以及流量方案】
U41568 Agent1 题目背景 2018年11月17日,中国香港将会迎来一场XM大战,是世界各地的ENLIGHTENED与RESISTANCE开战的地点,某地 的ENLIGHTENED总部也想派 ...
- noip提高组模拟赛(QBXT)T2
T2count题解 [ 问题描述]: 小 A 是一名热衷于优化各种算法的 OIER,有一天他给了你一个随机生成的 1~n 的排列, 并定 义区间[l,r]的价值为: \[ \huge C_{l,r}= ...
- [LUOGU] NOIP提高组模拟赛Day1
题外话:以Ingress为题材出的比赛好评,绿军好评 T1 考虑枚举第\(i\)个人作为左边必选的一个人,那左边剩余\(i-1\)个人,选法就是\(2^{i-1}\),也就是可以任意选或不选,右侧剩余 ...
- l洛谷 NOIP提高组模拟赛 Day2
传送门 ## T1 区间修改+单点查询.差分树状数组. #include<iostream> #include<cstdio> #include<cstring> ...
- 计蒜客 2017 NOIP 提高组模拟赛(四)Day1 T2 小X的密室
https://nanti.jisuanke.com/t/17323 小 X 正困在一个密室里,他希望尽快逃出密室. 密室中有 N 个房间,初始时,小 X 在 1号房间,而出口在 N号房间. 密室的每 ...
随机推荐
- 创建进程,join方法,进程对象相关属性和方法,僵尸进程和孤儿进程,守护进程,互斥锁
创建进程 在python中提供了一个multiprocessing模块可以帮助我们使用多进程解决问题.在multiprocessing 模块中有一个类Process. from multiproces ...
- MySQL(8) - MySQL的事务机制
MySQL数据库的事务机制 1.1.事务的概念和特性 1.2.事务的隔离级别 repeatable read是mysql默认的事务隔离级别 #事务A #事务A,临时修改工资,未commit, STAR ...
- 137_Power BI 自定义矩阵复刻Beyondsoft Calendar
博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 前两天我们用PBI原生的视觉制作了自定义的热力图,今天我们来复刻一个Beyondsoft Calendar 1. ...
- SpringBoot 2.X 快速掌握
0.重写博文的原因 当初我的SpringBoot系列的知识是采用分节来写的,即:每一个知识点为一篇博文,但是:最近我霉到家了,我发现有些博文神奇般地打不开了,害我去找当初的markdown笔记,但是方 ...
- CabloyJS自带工作流引擎的文档清单
文档清单 CabloyJS自带工作流引擎文档已经整理出来,欢迎大家围观.拍砖 介绍 介绍 演示:CMS审批工作流 单元测试用例集 流程定义 基本概念 JSON规范 listener规范 listene ...
- python PIL 图片素描化
from PIL import Image import numpy as np a = np.asarray(Image.open("D://7.jpg").convert('L ...
- vue大型电商项目尚品汇(后台篇)day02
这几天更新有点小慢,逐渐开始回归状态了.尽快把这个后台做完,要开始vue3了 3.添加修改品牌 用到组件 Dialog 对话框,其中visible.sync这个配置是修改他的显示隐藏的,label-w ...
- Boogie's First Blog
这是boogie在博客园的第一篇随笔,祝大家身体健康,心情愉悦.
- 1.1 操作系统的第一个功能——虚拟化硬件资源 -《zobolの操作系统学习札记》
1.1 操作系统的第一个功能--虚拟化硬件资源 目录 1.1 操作系统的第一个功能--虚拟化硬件资源 问1:操作系统一般处于计算机系统的哪一个位置? 问2:管理硬件资源为什么要单独交给操作系统? 问3 ...
- 前端学习 linux —— shell 编程
前端学习 linux - shell 编程 shell 原意是"外壳",与 kernel(内核)相对应,比喻内核外的一层,是用户和内核沟通的桥梁.shell 有很多种,国内通常使用 ...