复习与回顾: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)\)

posted @ 2021-07-24 18:31  沼中蒻杨  阅读(291)  评论(0编辑  收藏  举报