2023.10.4

A

一个连通有向无环图,边权是字符串,对于以下两种情况求 \(1\rightarrow n\) 的最短路:

  • 以字符串长度为第一关键字,字典序为第二关键字比较字符串。

  • 以字典序为关键字比较字符串。

\(1\le n\le 10^5\)\(n-1\le m\le 5\times 10^5\)\(|w_i|\le 10^5\)\(\sum |w_i|\le 2\times 10^6\).

二合一。


B

\(f^k(x)\)\(f(x)\) 嵌套 \(k\) 次的结果。当 \(k\le 0\) 时,另外定义 \(f^k(x)=x\).

给出 \(B\)\(T\)\(L,R\),求

\[\sum_{i=L}^{R}\varphi^{\max_{j=1}^{i}\varphi(j)-B}(i) \]

\(1\le T\le 10^5\)\(1\le L\le R\le 10^9\)\(0\le B\le 10^9\).


唯一能做的一个题。

最大值的式子其实就是最接近 \(i\) 的质数 \(j-1,j\in P\).

首先 \(x\leftarrow \varphi(x)\) 这个操作的层数是严格 \(\le \lfloor\log p\rfloor+1\) 的。

设一个阈值 \(M\),由于质数密度可以暴力地把所有数分为 \([1,B]\)\([B+1,B+M]\)\((B+M,N]\) 三段,左边的 \(f(i)=i\),中间的预处理出来,右边的 \(f(i)=1\)。(中间的数比较少)

然后就做完了。

点击查看代码
#include<bits/stdc++.h>
#pragma GCC optimize(3)
#define ll long long
#define N 1000000000
#define M 1000
using namespace std;
int read(){
	int x=0,w=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*w;
}
int B;
map<int,int>phi;
bool isprime(int n){
	if(n<2)return false;
	if(n==2)return true;
	for(int i=2;i*i<=n;i++)
		if(n%i==0)return false;
	return true;
}
ll f[M+5];int g[M+5];
int getphi(int n){
	if(phi[n])return phi[n];
	int ret=n,tp=n;
	for(int i=2;i*i<=n;i++){
		if(n%i==0){
			ret-=ret/i;
			while(n%i==0)n/=i;
		}
	}
	if(n>1)ret-=ret/n;
	return phi[tp]=ret;
}
void init(){
	for(int i=B+1;i<=min(B+M,N);i++){
		if(isprime(i))g[i-B]=i-1-B;
		else g[i-B]=g[i-B-1];
	}
	for(int i=B+1;i<=min(B+M,N);i++){
		f[i-B]=i;
		for(;f[i-B]!=1&&g[i-B];g[i-B]--)
			f[i-B]=getphi(f[i-B]);
		f[i-B]+=f[i-B-1];
	}
}
int main(){
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
	int T=read();B=read();
	init();
	int L,R;ll ans;
	while(T--){
		L=read(),R=read();
		if(R<=B){
			ans=1ll*R*(R+1)/2-1ll*L*(L-1)/2;
			printf("%lld\n",ans);
			continue;
		}
		if(L>B+M){
			printf("%d\n",R-L+1);
			continue;
		}
		ans=0;
		if(L<=B)ans+=1ll*B*(B+1)/2-1ll*L*(L-1)/2;
		if(R>B+M)ans+=R-B-M;
		ans+=f[min(M,R-B)]-f[max(0,L-1-B)];
		printf("%lld\n",ans);
	}
	
	return 0;
}

C

给出一棵以 \(1\) 为根的树,将 \(n\) 阶排列分配到每个节点上,最大化 \(w_u<w_{\operatorname{lca}(u,v)}<w_v\)\((u,v)\) 对数。输出这个值。

\(n\le 10^6\).


对于每个节点 \(u\) 作为 lca,最优时不妨将 \(u\) 的所有儿子子树 \(v\) 分成两份,令这些子树分别小于或大于 \(w_u\).

也就是要把儿子字数大小均分,直接 dp 不是很理想。


D

初始有一个小写字母串 \(S\)(下标从 \(1\) 开始),支持:

  • 在位置 \(p\) 后插入字符串 \(s\)

  • 删除 \([l,r]\) 的字符

  • \([l,r]\) 的字符替换为字符串 \(s\)

  • 查询 \([l,r]\) 中有多少字符 \(c\)

  • 查询 \([l,r]\) 间模式串 \(P\) 的出现次数

\(1\le n\le 10^5\)\(|s|\le 10^5\)\(\sum |s|\le 10n\)\(|P|\le 20\).

posted @ 2023-10-04 15:09  SError  阅读(13)  评论(0编辑  收藏  举报