复习与回顾:2021.7.9 contest 2
复习与回顾:2021.7.9 contest 2
A
Description
给定 \(n,m\) ,求有多少个正整数 \(x\),使得 \(x^m \leq n\)。
Input
一行两个正整数 \(n,m\) 。
Output
一个整数表示正整数 \(x\) 的个数。
Example
input
5 2
output
2
Hint
满足 \(1 \leq n,m \leq 10^9\)
Solution
不动脑子:直接二分
稍微动下脑子:特判\(m=1\)后直接枚举复杂度不超过\(O(logn)\)
总之是签到题
B
Description
给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1 \leq i < j \leq n\) ,若 \(|i-j|\) 为质数,则 \(i\) 和 \(j\) 不同色。求出颜色尽可能少的染色方案。如果有多种方案,输出任意一种即可。
Input
第一行一个整数 \(n\) 。
Output
第一行一个整数 \(K\),表示颜色数。
第二行 \(n\) 个整数 \(col_i(1 \leq col_i \leq K)\),表示 \(i\)的颜色。
Example
input
7
output
4
1 2 2 3 3 4 1
Hint
满足 \(1 \leq n \leq 10^4\)
Solution
首先显然随着 \(n\) 增大答案单调不减
手玩一下可以发现 \(12341234...1234\) 这样每四个一组的染色方案一定满足条件
写个爆搜可以发现从 \(n=7\) 开始答案是 \(4\)
于是对于 \(n < 7\) 直接爆搜, \(n \geq 7\) 就使用上面的方案
C
Description
小QwQ
在批改作业的时候发现大家的提交的文件名都很不规范,这让他很头疼。作为一个强迫症患者,他决定手动规范大家的文件名。但是有些人的文件名特别长,他想要知道最少需要修改多少次才能够使得字符串 \(A\) 变成字符串 \(B\)。当然对于修改代价超过 \(K\) 的文件名我们会选择放弃。
每次修改可在 \(A\) 中添加或删除一个字符。
Input
输入共包含 \(3\) 行。
第 \(i\)行包含三个整数 \(n,m,K\) ,分别表示原始串 \(A\) 的长度 \(n\) ,目标串 \(B\) 的长度 \(m\) 和限制的最大修改次数 \(K\)。
接下来 \(2\) 行,分别输入原始字符串 \(A\) 和目标字符串 \(B\)。
Output
输出共包含 \(1\) 行,如果最小修改次数小于等于 \(K\) ,则输出最少修改次数,不然输出 \(-1\)。
Example
input
3 4 2
bee
beef
output
1
Hint
满足 \(0 \leq n,m \leq 500000\ ,\ 0 \leq K \leq 100\)。字符串中只包含小写字母
Solution
显然当 \(|n-m| > K\) 时无解
对 \(A\) 增添字符可以等价为对 \(B\) 删减字符
考虑DP,设 \(f_{i,j}\) 表示将\(A\)的前\(i\)位修改为\(B\)的前\(j\)位所需最小代价,易得转移式:\(f_{i,j}=min\left\{\ \ f_{i-1,j}\ \ ,\ \ f_{i,j-1}\ \ ,\ \ (f_{i-1,j-1}+[A_i=B_j]*1)\ \ \right\}\) 此时复杂度 \(O(n*m)\)
回到第一句话,发现任意时刻若 \(|i-j| > K\) 则一定不会转移至终态,于是修改DP状态,令 \(f_{i,t}\) 表示将\(A\)的前\(i\)位修改为\(B\)的前\(j\)位\((i-j=\ t \in [-K,K])\)所需最小代价,转移式与上式类似,复杂度 \(O(nK)\)
Code
#define Min(a,b) ((a)>(b)?(a)=(b):0)
void Solve(){
F[0][100]=0;
for(int i=1;i<=K;i++)F[0][100+i]=i;
for(int i=1;i<=K;i++)F[i][100-i]=i;
for(int i=1;i<=n;i++){
for(int j=max(1,i-K),je=min(m,i+K);j<=je;j++){
F[i][j-i+100]=(sn[i]==sm[j]?F[i-1][j-i+100]:i+j);
if(abs(j-i+1)<=K)Min(F[i][j-i+100],F[i-1][j-i+1+100]+1);
if(abs(j-1-i)<=K)Min(F[i][j-i+100],F[i][j-1-i+100]+1);
}
}
if(F[n][m-n+100]<=K)
cout<<F[n][m-n+100]<<'\n';
else cout<<"-1\n";
}
D
Description
你有一棵 \(n\) 节点的树 \(T\) ,回答 \(m\) 个询问,每次询问给你两个整数 \(l,r\),问存在多少个整数 \(k\) 使得从树上编号为 \(l\) 的点沿着 \(l \rightarrow r\) 的简单路径走 \(k\) 步恰好到达编号为 \(k\) 的点。
Input
第一行两个整数 \(n,m\) ,表示节点数和询问数。
之后 \(n-1\) 行,每行两个整数 \(u,v\) 表示一条边。
之后 \(m\) 行,每行两个整数 \(l,r\) 表示 一个询问,题意同题目描述。
Output
\(m\) 行,对于每个询问单独输出一行表示你的答案。
Example
input
9 3
5 4
4 3
3 7
4 1
1 6
1 8
1 9
5 2
6 7
2 3
3 2
output
2
1
0
Hint
满足 \(1 \leq n,m \leq 3*10^5\)
Solution
记 \(lca(l,r)\) 为 \(c\) ,对于 \(l \rightarrow r\) 的一段路径,考虑拆成向上的 \(l \rightarrow c \ (*)\) 和向下的 \(c \rightarrow r\ (**)\)
对于 \((*)\) ,某个 \(k\) 产生贡献当且仅当:\(dep_l-dep_k=k \ \Longleftrightarrow\ dep_l=dep_k+k\)
对于 \((**)\) ,某个 \(k\) 产生贡献当且仅当:\((dep_l-dep_c)+(dep_r-dpe_c)-(dep_r-dep_k)=k\ \Longleftrightarrow\ dep_l-2dep_c=k-dep_k\)
发现整理后询问与贡献分离,使用树上可持久化线段树来统计贡献,总复杂度\(O((n+m)\ logn)\)
本文来自博客园,作者:蒻杨,转载请注明原文链接:https://www.cnblogs.com/weed-yang/