专栏文章

2025 乔斯集训

个人记录参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miojp15n
此快照首次捕获于
2025/12/02 20:19
3 个月前
此快照最后确认于
2025/12/02 20:19
3 个月前
查看原文

2025 乔斯集训

注:具体内容可见课件/deepseek/OI Wiki

DAY 1

上午:

1. 广搜拓展 bfs spfa floyd
普通最短路 + 带权最短路
普通最短路:队列 queue 队尾插入删除
带权最短路: 01广搜 时间复杂度和普通广搜一样
2. 01广搜 时间复杂度和普通广搜一样
双端队列 deque 支持从队首队尾插入删除元素
链式前向星
点个数 n<=10^5 边条数 m<=10^6 一张有向图 边权0或1 求点1到其他点的最短路
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
const int maxn=100100;
const int maxm=1001000;
struct node{
	int next,to,len;
}edge[maxm];
int h[maxn],tot;
int n,m;
deque<int> T;
int dis[maxn],vis[maxn];
void add(int x,int y,int z){
	tot++;
	edge[tot].to=y;
	edge[tot].len=z;
	edge[tot].next=h[x];
	h[x]=tot;
} 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i=1;i<=m;i++){
		int x,y,z;
		cin >> x >> y >> z;
		add(x,y,z);
	}
	memset(dis,0x3f,sizeof(dis));
	dis[1]=0;
	T.push_back(1);
	while (!T.empty()){
		int u=T.front();
		T.pop_front();
		if (vis[u]){
			continue;
		}
		vis[u]=1;
		for (int i=h[u];i;i=edge[i].next){
			int to=edge[i].to;
			dis[to]=min(dis[to],dis[u]+edge[i].len);
			if (edge[i].len==0){
				T.push_front(to);
			}
			else{
				T.push_back(to);
			}
		}
	}
	cout << dis[某一个点];
	return 0;
}
Bishop 2 bfs练习
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
char a[1510][1510];
int kf[5][2]={{},{1,1},{1,-1},{-1,1},{-1,-1}}; 
deque<array<int,4>> q;
int dis[1510][1510][5]; 
int INF=1e9;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin >> n;
	int qx,qy;
	cin >> qx >> qy;
	int zx,zy;
	cin >> zx >> zy;
	for (int i=1;i<=n;i++){
		for (int j=1;j<=n;j++){
			cin >> a[i][j];
		}
	}
	fill(dis[0][0],dis[n+1][0],INF);
//	for (int i=0;i<=n+1;i++){
//		for (int j=0;j<=4;j++){
//			dis[i][0][j]=INF;
//		}	
//	}
	q.push_back({qx,qy,0,0});//坐标 方向 步数 
	while (!q.empty()){
		auto p=q.front();
		q.pop_front();
		if (a[p[0]][p[1]]=='.' && dis[p[0]][p[1]][p[2]]==INF){
			dis[p[0]][p[1]][p[2]]=p[3];
			q.push_front({p[0]+kf[p[2]][0],p[1]+kf[p[2]][1],p[2],p[3]});
			for (int i=1;i<=4;i++){
				q.push_back({p[0],p[1],i,p[3]+1});
			}
		}
	}
	int sum=min({dis[zx][zy][1],dis[zx][zy][2],dis[zx][zy][3],dis[zx][zy][4]});
	if (sum==INF){
		cout << -1;
	}
	else{
		cout << sum;
	}
	return 0;
}

5
1 3
3 5
....#
...#.
.....
.#...
#....


3
例题 P5 Chamber of Secrets
错误原因:忘记给距离数组初始化(0x3f),输出n,m写错,4个方向0-3写成0-4
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
char a[1010][1010];
int n,m;
// 右下左上
//  0 1 2 3 
struct node{
	int next,tox,toy,tod,len;//  行 列 方向 
}edge[1010*1010*20]; 
int h[1010][1010][4],tot;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0}; 
void add(int x,int y,int d,int dx,int dy,int dd,int bq){
//	tot++;
//	edge[tot].tox=x; 
//	edge[tot].toy=y; 
//	edge[tot].tod=d; 
//	edge[tot].len=bq;
//	edge[tot].next=h[x][y][d]; 
//	h[x][y][d]=tot;
	tot++;
	edge[tot].tox=dx; 
	edge[tot].toy=dy; 
	edge[tot].tod=dd; 
	edge[tot].len=bq;
	edge[tot].next=h[x][y][d]; 
	h[x][y][d]=tot;
}
int dis[1010][1010][4],vis[1010][1010][4];
deque<pair<pair<int,int>,int>> q;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i=1;i<=n;i++){
		for (int j=1;j<=m;j++){
			cin >> a[i][j];
			if (a[i][j]=='#'){//有镜子 
				for (int k=0;k<=3;k++){
					for (int o=0;o<=3;o++){
						if (k!=o){
							add(i,j,k,i,j,o,1);
						}
					}
				}
			}
			//四个方向移动 
			for (int k=0;k<=3;k++){
				if (i+dx[k]>=1 && i+dx[k]<=n && j+dy[k]>=1 && j+dy[k]<=m){
					add(i,j,k,i+dx[k],j+dy[k],k,0);
				}
			}
		}
	} 
	bool fg=0; 
	for (int i=1;i<=m;i++){
		if (a[n][i]=='#'){
			fg=1;
		}
	}
	if (fg==0){
		cout << -1;
		return 0;
	}
	q.push_back({{1,1},0});
	memset(dis,0x3f3f3f,sizeof(dis)); 
	dis[1][1][0]=0;
	while (!q.empty()){
		pair<pair<int,int>,int> p=q.front();
		//cout << p.first.first << " " << p.first.second << " " << p.second << endl;
		q.pop_front();
		if (vis[p.first.first][p.first.second][p.second]){
			continue;
		}
		vis[p.first.first][p.first.second][p.second]=1;
		for (int i=h[p.first.first][p.first.second][p.second];i;i=edge[i].next){
			int x=edge[i].tox,y=edge[i].toy,d=edge[i].tod;
			dis[x][y][d]=min(dis[x][y][d],dis[p.first.first][p.first.second][p.second]+edge[i].len);
			if (edge[i].len==0){
				q.push_front({{x,y},d});
			}
			else{
				q.push_back({{x,y},d});
			}
		}
	}
	if (dis[n][m][0]==0){
		cout << -1;
	} 
	else{
		cout << dis[n][m][0]; 
	}
	return 0;
}
3. 折半搜索 dfs
分别暴力搜索前半边和后半边
结果存储
前半边枚举,后半边二分/lower_bound
例题 P6 世界冰球锦标赛
错误原因:方法种数计算错误
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int n;
long long m;
long long a[50];
long long l[10000010],r[10000010],cnt=0,mnk=0;
void dfs1(int x,long long sum){
	if (x==n/2+1){
		cnt++;
		l[cnt]=sum;
		return;
	}
	dfs1(x+1,sum+a[x]);
	dfs1(x+1,sum);
}
long long num=0;
void dfs2(int x,long long sum){
	if (sum>m){
		return;
	}
	if (x==n+1){
		num+=upper_bound(l+1,l+cnt+1,m-sum)-l-1;
		return;
	}
	dfs2(x+1,sum);
	dfs2(x+1,sum+a[x]);
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	}
	dfs1(1,0);
//	cout << cnt << " " << mnk << endl;
	sort(l+1,l+cnt+1);
	dfs2(n/2+1,0);
	cout << num;
	return 0;
}

下午

1.树上差分(边差分+点差分)
LCA(最近公共祖先):分两部分计算
1:到达同一水平位置
2:到达最近公共祖先的儿子
倍增
预处理 f[i][j]往根方向走2^j 到达的点
f[i][j]=f[f[i][j-1]][j-1];
点的距离:(lca)模板
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
const int maxn=100100;
struct node{
	int next,to;
}edge[maxn*2];
int f[maxn][22];// 2^20>100000 
int h[maxn],tot,dep[maxn];
int n;
void add(int x,int y){
	tot++;
	edge[tot].to=y;
	edge[tot].next=h[x];
	h[x]=tot;
}
void dfs(int x,int fa){
	for (int i=h[x];i;i=edge[i].next){
		int to=edge[i].to;
		if (to==fa){
			continue;
		}
		dep[to]=dep[x]+1;
		f[to][0]=x; 
		dfs(to,x);
	}
}
int q;
int lca(int x,int y){
	if (dep[y]>dep[x]){
		swap(x,y);
	}
	int tmp=dep[x]-dep[y];
	int tim=0;
	while (tmp){
		if (tmp&1){
			x=f[x][tim];
		}
		tim++;
		tmp>>=1;
	}
//	for (int i=20;i>=0;i--){
//		if (dep[x]-(1<<i)>=dep[y]){
//			x=f[x][i];
//		}
//	}
	if (x==y){
		return x;
	}
	for (int i=20;i>=0;i--){
		if (f[x][i]!=f[y][i]){
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[x][0];
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i=1;i<=n-1;i++){
		int x,y;
		cin >> x >> y;
		add(x,y);
		add(y,x);
	}
	dfs(1,0);
	for (int j=1;(1<<j)<=n;j++){
		for (int i=1;i<=n;i++){
			f[i][j]=f[f[i][j-1]][j-1];
		//	cout << f[i][j] << " "; 
		}
	}
	cin >> q;
	for (int i=1;i<=q;i++){
		int x,y;
		cin >> x >> y;
		int lc=lca(x,y);
		cout << dep[x]-dep[lc]+dep[y]-dep[lc] << endl;
	}
	return 0;
}
Fools and Roads lca+边差分模板
边差分模板:
C
int sum[100100],ans;
void fs(int x,int fa){
	for (int i=h[x];i;i=edge[i].next){
		int to=edge[i].to;
		if (to==fa){
			continue;
		}
		fs(to,x);
		sum[x]+=sum[to];
	}
} 
sum[x]++;
sum[y]++;
sum[lc]-=2;
fs(1,0);
for (int i=2;i<=n;i++){
	cout << sum[i] << " ";
}


#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
const int maxn=100100;
struct node{
	int next,to;
}edge[maxn*2];
int f[maxn][22];// 2^20>100000 
int h[maxn],tot,dep[maxn];
int n;
void add(int x,int y){
	tot++;
	edge[tot].to=y;
	edge[tot].next=h[x];
	h[x]=tot;
}
void dfs(int x,int fa){
	for (int i=h[x];i;i=edge[i].next){
		int to=edge[i].to;
		if (to==fa){
			continue;
		}
		dep[to]=dep[x]+1;
		f[to][0]=x; 
		dfs(to,x);
	}
}
int q;
int lca(int x,int y){
	if (dep[y]>dep[x]){
		swap(x,y);
	}
	int tmp=dep[x]-dep[y];
	int tim=0;
	while (tmp){
		if (tmp&1){
			x=f[x][tim];
		}
		tim++;
		tmp>>=1;
	}
//	for (int i=20;i>=0;i--){
//		if (dep[x]-(1<<i)>=dep[y]){
//			x=f[x][i];
//		}
//	}
	if (x==y){
		return x;
	}
	for (int i=20;i>=0;i--){
		if (f[x][i]!=f[y][i]){
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[x][0];
}
int sum[100100],ans;
void fs(int x,int fa){
	for (int i=h[x];i;i=edge[i].next){
		int to=edge[i].to;
		if (to==fa){
			continue;
		}
		fs(to,x);
		sum[x]+=sum[to];
	}
} 
int main(){
	//边差分 
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i=1;i<=n-1;i++){
		int x,y;
		cin >> x >> y;
		add(x,y);
		add(y,x);
	}
	dfs(1,0);
	for (int j=1;(1<<j)<=n;j++){
		for (int i=1;i<=n;i++){
			f[i][j]=f[f[i][j-1]][j-1];
		//	cout << f[i][j] << " "; 
		}
	}
	cin >> q;
	for (int i=1;i<=q;i++){
		ans=0;
		int x,y;
		cin >> x >> y;
		int lc=lca(x,y);
		sum[x]++;
		sum[y]++;
		sum[lc]-=2;
		//cout << dep[x]-dep[lc]+dep[y]-dep[lc] << endl;
	}
	fs(1,0);
	for (int i=2;i<=n;i++){
		cout << sum[i] << " ";
	}
	return 0;
}
点差分模板:
C
int sum[300100];
void fs(int x,int fa){
	for (int i=h[x];i;i=edge[i].next){
		int to=edge[i].to;
		if (to==fa){
			continue;
		}
		fs(to,x);
		sum[x]+=sum[to];
	}
} 
sum[x]++;
sum[y]++;
sum[lc]--;
if (lc!=1){
	sum[f[lc][0]]--;
}
fs(1,0);
for (int i=2;i<=n;i++){
	sum[a[i]]--;
} 
for (int i=1;i<=n;i++){
	cout << sum[i] << endl; 
}
松鼠的新家 lca+点差分模板
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
const int maxn=300100;
struct node{
	int next,to;
}edge[maxn*2];
int f[maxn][22];// 2^20>100000 
int h[maxn],tot,dep[maxn];
int n;
int a[300100];
void add(int x,int y){
	tot++;
	edge[tot].to=y;
	edge[tot].next=h[x];
	h[x]=tot;
}
void dfs(int x,int fa){
	for (int i=h[x];i;i=edge[i].next){
		int to=edge[i].to;
		if (to==fa){
			continue;
		}
		dep[to]=dep[x]+1;
		f[to][0]=x; 
		dfs(to,x);
	}
}
int q;
int lca(int x,int y){
	if (dep[y]>dep[x]){
		swap(x,y);
	}
	int tmp=dep[x]-dep[y];
	int tim=0;
	while (tmp){
		if (tmp&1){
			x=f[x][tim];
		}
		tim++;
		tmp>>=1;
	}
//	for (int i=20;i>=0;i--){
//		if (dep[x]-(1<<i)>=dep[y]){
//			x=f[x][i];
//		}
//	}
	if (x==y){
		return x;
	}
	for (int i=20;i>=0;i--){
		if (f[x][i]!=f[y][i]){
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[x][0];
}
int sum[300100];
void fs(int x,int fa){
	for (int i=h[x];i;i=edge[i].next){
		int to=edge[i].to;
		if (to==fa){
			continue;
		}
		fs(to,x);
		sum[x]+=sum[to];
	}
} 
int main(){
	//点差分 
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	}
	for (int i=1;i<=n-1;i++){
		int x,y;
		cin >> x >> y;
		add(x,y);
		add(y,x);
	}
	dfs(1,0);
	for (int j=1;(1<<j)<=n;j++){
		for (int i=1;i<=n;i++){
			f[i][j]=f[f[i][j-1]][j-1];
		//	cout << f[i][j] << " "; 
		}
	}
	for (int i=1;i<n;i++){
		int x=a[i],y=a[i+1];
		int lc=lca(x,y);
		sum[x]++;
		sum[y]++;
		sum[lc]--;
//		sum[f[lc][0]]--; 
		if (lc!=1){
			sum[f[lc][0]]--;
		}
		//cout << dep[x]-dep[lc]+dep[y]-dep[lc] << endl;
	}
	fs(1,0);
	for (int i=2;i<=n;i++){
		sum[a[i]]--;
	} 
	for (int i=1;i<=n;i++){
		cout << sum[i] << endl; 
	}
	return 0;
}

晚上

A 小杨的养??(熊)计划
B 强哥的传送带

DAY 2

上午

讲解昨晚比赛题目
小杨的养??(熊)计划 //前缀和+分别统计
C
#include<bits/stdc++.h>
using namespace std;
const double PI=acos(-1.0);
long long a[20010],b[20010];
map<long long,long long> mp; 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n,x,y,z;
	cin >> n >> x >> y >> z;
	for (long long i=1;i<=n;i++){
		cin >> a[i] >> b[i];
		mp[a[i]]+=y-x;
		mp[b[i]+1]+=z-y;
	} 
	long long maxx=x*n,sum=x*n;
	for (auto it:mp){
		sum+=it.second;
		maxx=max(maxx,sum);
	}
	cout << maxx;
	//前缀和+分别统计
	return 0;
}
强哥的传送带 (尚未AC)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
const int maxn=100100;
const int maxm=170; 
int n,m;
//  f[x][p] 在x号站点出发,第一个能访问到的包含p这个质因子的编号
// list[p] :拥有p这个质因子的元素的线性表 
int prime[100100];
int cnt;
int a[100100];
int l[1010][1010];
int f[10010][1010]; 
int main(){
	freopen("dijkstra.in","r",stdin);
	freopen("dijkstra.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i=1;i<=n;i++){
		cin >> a[i];
		int x=a[i];
		//特殊的,如果a[i]等于0,默认他拥有所有的质数做质因子 
		for (int j=2;j*j<=x;j++){
			if (x%j==0){
				l[j][++l[j][0]]=i;
				while (x%j==0){
					x/=j;
				}
			}
		} 
		if (x>1){
			l[x][++l[x][0]]=i;
		}
	}
	bool fg=0;
	for (int i=2;i<=1000;i++){
		for (int j=2;j<i;j++){
			if (i%j==0){
				fg=1;
				break;
			}
		}
		if (fg==1){
			cnt++;
			prime[cnt]=i;
		}
	}
	memset(f,0x3f,sizeof(f));
	for (int i=n-1;i>=1;i--){
		int x=a[i];
		//特殊的,如果a[i]等于0,默认他拥有所有的质数做质因子 
		for (int j=2;j*j<=x;j++){
			if (x%j==0){
				while (x%j==0){
					x/=j;
				}
				//找到下一个拥有质因子j的数,并且进行转移
				int nxt=upper_bound(l[j]+1,l[j]+l[j][0]+1,i)-l[j];
				if (nxt<=l[j][0]){
					f[i][j]=nxt; //连边p:枚举2~1000质数 
					for (int p=1;p<=cnt;p++){//找路径 
						if (j!=prime[p]){
							f[i][prime[p]]=min(f[i][prime[p]],f[nxt][prime[p]]);
						} 
					}
				}
			}
		} 
		if (x>1){
			l[x][++l[x][0]]=i;
		}
	} 
	for (int i=1;i<=m;i++){
		int x,y;
		cin >> x >> y;
		//对a[y]分解质因数
		int tmp=a[y];
		bool flag=0;
		for (int j=2;j*j<=tmp;j++){
			if (tmp%j==0){
				while (tmp%j==0){
					tmp/=j;
				}//发现a[y] 
				if (f[x][j]<=y){
					flag=1;
				}
			}
			if (tmp>1){
				if (f[x][j]<=y){
					flag=1;
				}
			}
		} 
		
		if (flag==1){
			cout << "Yes" << endl;
		}
		else{
			cout << "No" << endl;
		}
	}
	return 0;
}
/*
1-5
1-3
2-3
3-4
3-5
2-4
4-5

下午

动态规划:
1.背包 资源分配->获取价值 模板见洛谷个人笔记(记得复习)
2.状压DP
背包:
武器购买
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int p[110],c[110]; 
int dp[110][500010];
int main(){
	int t;
	cin >> t;
	while (t--){
		int n,P,Q;
		cin >> n >> P >> Q;
		int sum=0;
		for (int i=1;i<=n;i++){
			cin >> p[i] >> c[i];
			sum+=p[i];
		}
		memset(dp,0,sizeof(dp));
		for (int i=1;i<=n;i++){
			for (int j=1;j<=Q;j++){
				dp[i][j]=dp[i-1][j];
				if (c[i]<=j){
					dp[i][j]=max(dp[i][j],dp[i-1][j-c[i]]+p[i]);
				}	
			}
		}
		bool fg=0;
		for (int i=1;i<=Q;i++){
			if (dp[n][i]>=P){
				cout << i << endl;
				fg=1;
				break;
			}
		}
		if (fg==0){
			cout << -1 << endl;
		}
//		for (int i=1;i<=sum;i++){
//			cout << dp[i] << " ";
//		}
//		cout << endl;
	} 
	return 0;
}
道路优化
C
#include<bits/stdc++.h>
using namespace std;
long long n,l,k;
struct node{
	long long wz,xs;
}a[600];
long long dp[510][510];//表示到达第i个限速点时,已经删除了j个限速点时的最短时间
long long pl; 
int main(){
	ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> l >> k;
    for (int i=1;i<=n;i++){
    	cin >> a[i].wz;
	}
	for (int i=1;i<=n;i++){
		cin >> a[i].xs;
	}
	a[n+1].wz=l;
	a[n+1].xs=0;
	memset(dp,0x3f,sizeof(dp));
	dp[1][0]=0;
	n++; 
	for (int i=1;i<=n;i++){
		for (int j=0;j<=k;j++){
			for (int m=1;m<i;m++){
				pl=j-(i-m-1);
				if (pl>=0 && pl<=k && dp[m][pl]!=0x3f){
					dp[i][j]=min(dp[i][j],dp[m][pl]+a[m].xs*(a[i].wz-a[m].wz));
				}
			}
		}
	} 
	long long minn=INT_MAX;
	for (int i=0;i<=k;i++){
	//	cout << dp[n][i] << " ";
		minn=min(minn,dp[n][i]);
	}
	cout << minn;
	return 0;
}
状压dp
GEPPETTO
1.暴搜
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int a[50],b[50];
int s[50][50];
int f[50];
int sum;
int n,m;
void dfs(int x,int cnt){
	if (x==n+1){
		sum++;
		return;
	}
	bool fg=0;
	for (int i=1;i<=cnt;i++){
		if (s[f[i]][x]==1 || s[x][f[i]]==1){
			fg=1;
			break;
		}
	}
	if (fg==0){
		cnt++;
		f[cnt]=x;
		dfs(x+1,cnt);
		cnt--;
	}
	dfs(x+1,cnt);
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i=1;i<=m;i++){
		cin >> a[i] >> b[i];
		s[a[i]][b[i]]=1;
		s[b[i]][a[i]]=1;
	}
	dfs(1,0);
	cout << sum;
	return 0;
}
2.二进制压缩(状压dp)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int x[55],y[55];
int n,m;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i=1;i<=m;i++){
		cin >> x[i] >> y[i];
	}
	int ans=(1<<n);
	for (int i=0;i<(1<<n);i++){
		for (int j=1;j<=m;j++){
			//检查方案i里面是否包含x[j]和y[j]两种原材料
			//检查的是 i在2^(x[j]-1)和2^(y[j]-1)这两位的取值
			if ((i&(1<<(x[j]-1))) && (i&(1<<(y[j]-1)))){
				ans--;
				break;
			}
		}
	}
	cout << ans;
	return 0;
}
互不侵犯
C
#include<bits/stdc++.h>
using namespace std;
long long dp[11][110][110],ans;
long long num[110],s[110],n,l,ol;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	// f[i][j][p]第i行国王放置方案为j且总国王个数为p时的时候合法方案个数
	cin >> n >> l;
	ol=0;
	ans=0;
	memset(dp,0,sizeof(dp));
	for (int i=0;i<(1<<n);i++){
		if (i&(i<<1)){//相邻 
			continue;
		}
		long long op=0;
		for (int j=0;j<n;j++){
			if (i&(1<<j)){
				op++;
			}
		}
		s[++ol]=i;
		num[ol]=op;
		//记录合法状态 
	}//预处理合法状态
	dp[0][1][0]=1;//初始化 
	for (int i=1;i<=n;i++){//遍历 
		for (int j=1;j<=ol;j++){//当前合法状态 
			for (int k=0;k<=l;k++){//棋子数量 
				if (k>=num[j]){
					for (int t=1;t<=ol;t++){//上一行合法状态 
						if (!(s[t]&s[j]) && !(s[t]&(s[j]<<1)) && !(s[t]&(s[j]>>1))){
							dp[i][j][k]+=dp[i-1][t][k-num[j]];//状态转移 
						}
					}
				}
			}
		}
	}
	for (int i=1;i<=ol;i++){
		ans+=dp[n][i][l];//方案统计 
	}
	cout << ans;
	return 0;
} 
金明的预算方案
C
#include<bits/stdc++.h>
using namespace std;
long long v[100],w[100],q[100];
struct node{
	long long vv,ww;
}fa[100][3];
long long zv[100],zw[100];
long long cnt=0;
long long dp[33010];
long long pj[110];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long m,n;
	cin >> m >> n;
	for (int i=1;i<=n;i++){
		cin >> v[i] >> w[i] >> q[i];
		if (q[i]==0){
			cnt++;
			pj[i]=cnt;
			zv[cnt]=v[i];
			zw[cnt]=w[i];
		}
	}
	for (int i=1;i<=n;i++){
		if (fa[pj[q[i]]][1].vv!=0 || fa[pj[q[i]]][1].ww!=0){
			fa[pj[q[i]]][2].vv=v[i];
			fa[pj[q[i]]][2].ww=w[i];
		}
		else{
			fa[pj[q[i]]][1].vv=v[i];
			fa[pj[q[i]]][1].ww=w[i];
		}
	}
	memset(dp,0,sizeof(dp));
	for (int i=1;i<=cnt;i++){
		for (int j=m;j>=zv[i];j--){
			dp[j]=max(dp[j],dp[j-zv[i]]+zw[i]*zv[i]);//不选附件,只决定选不选附件 
			if (j-zv[i]-fa[i][1].vv>=0){
				dp[j]=max(dp[j],dp[j-zv[i]-fa[i][1].vv]+zw[i]*zv[i]+fa[i][1].vv*fa[i][1].ww);//附1 
			}
			if (j-zv[i]-fa[i][2].vv>=0){
				dp[j]=max(dp[j],dp[j-zv[i]-fa[i][2].vv]+zw[i]*zv[i]+fa[i][2].vv*fa[i][2].ww);//附2
			}
			if (j-zv[i]-fa[i][1].vv-fa[i][2].vv>=0){
				dp[j]=max(dp[j],dp[j-zv[i]-fa[i][1].vv-fa[i][2].vv]+zw[i]*zv[i]+fa[i][1].vv*fa[i][1].ww+fa[i][2].vv*fa[i][2].ww);//附1附2  
			}
		}
	}
	cout << dp[m];
	return 0;
}

晚上

模拟赛2

1.小杨的字符串难题

2.拆墙大作战

3.强哥的积木

DAY 3

上午

讲解模拟赛题目
小杨的字符串难题
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long a[20];
long long b[5000010];
long long cnt; 
long long c[1250];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	string s;
	cin >> s;
	//二进制表示 
	//前缀数字 
	long long sum=0;
	cnt++;
	b[cnt]=sum;
	for (int i=0;i<s.size();i++){
		a[s[i]-'0']++;
		if (a[s[i]-'0']%2==1){
			sum+=pow(2,s[i]-'0');
		}
		else{
			sum-=pow(2,s[i]-'0');
		}
		cnt++;
		b[cnt]=sum;
	} 
	for (int i=1;i<=cnt;i++){
	//	cout << b[i] << " ";
		c[b[i]]++;
	}
//	cout << endl;
	long long ans=0;
	for (int i=0;i<=1200;i++){
		//cout << c[i] << " ";
		if (c[i]>1){
			ans=ans+(c[i]-1)*c[i]/2;
		}
	} 
	cout << ans;
	return 0;
}
/*
1 2 3 4
1234

20230322

0:0
1:4
2:5
3:1
4:9
5:8
6:0
7:4
8:0
拆墙大作战
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
struct node{
	long long l,r;
}a[200010];
bool cmp(node s1,node s2){
	return s1.r<s2.r;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n,d;
	cin >> n >> d;//贪心 
	for (int i=1;i<=n;i++){
		cin >> a[i].l >> a[i].r;
	}
	sort(a+1,a+n+1,cmp); 
	long long ol=0;
	long long i=1;
	while (i<=n){
		long long gj=a[i].r;
	//	long long x=max(a[i].l,gj-d+1); //起点 
		ol++;
		while (i<=n && a[i].l<=gj+d-1){//同时攻击到的 
			i++;
		}
	}
	cout << ol;
	return 0;
}
/*a:10
123456789a
**      
   ****
    *****


**        
***        
       ***
**    
    **
     **

强哥的积木 80分 (尚未AC)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long a[40];
string s;
string y,t;
long long n,m;
void dfs(int k,string g){
	if (g<y){
		y=g;
	}
	if (k==0){
		return;
	}
	t=g;
	for (int i=1;i<s.size();i++){
		t=g;
		swap(t[i],t[i-1]);
		dfs(k-1,t);
	}
}
vector<long long> b[30];
long long fg[500010];
deque<char> q;
deque<char> p;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	cin >> s; //暴搜 
	y=s;
	if (m==0){
		cout << s;
		return 0;
	}
	else if (m==1000000000000000000){
		for (int i=0;i<s.size();i++){
			a[s[i]-'a']++;
		}
		for (int i=0;i<=26;i++){
			if (a[i]!=0){
				for (int j=1;j<=a[i];j++){
					cout << char(i+'a');
				}
			}
		}
		return 0;
	}
	else if (n<=5 && m<=10){
		dfs(m,s);
		cout << y; 
		return 0;
	}
//	for (int i=0;i<s.size();i++){
//		a[s[i]-'a']++;
//		b[s[i]-'a'].push_back(i);
//	}
//	int kt=0;
//	for (int i=0;i<=25;i++){
//		if (char('a'+i)>s[kt]){
//			kt++;
//			continue;
//		}
//		if (char('a'+i)==s[kt]){
//			kt++;
//		}
//		for (auto it:b[i]){
//			if (it-kt>m){
//				for (int j=it;j>=it-m+1;j--){
//					swap(s[j],s[j-1]);
//				}
//				break;
//			}
//			for (int j=it;j>=kt+1;j--){
//				swap(s[j],s[j-1]);
//			}
//			m-=(it-kt);
//			kt++;
//		}
//		if (m==0){
//			break;
//		}
//	}
//	cout << s;
	for (int i=0;i<s.size();i++){
		q.push_back(s[i]);
	}
	while (m>0 && !q.empty()){
//		int o=0;
//		int minn=INT_MAX;
//		char yh='z';
//		while (!q.empty()){
//			o++;
//			if (q.front()<yh){
//				yh=q.front();
//				minn=o;
//			}
//			p.push_back(q.front());
//			q.pop_front();
//		}
//		while (!p.empty()){
//			q.push_back(p.front());
//			p.pop_front();
//		}
//		m-=o;
//		cout << yh;
//		q.erase(q.begin()+o);
//		p.clear(); 
		auto it=min_element(q.begin(),q.begin()+min(m+1,(long long)(q.size())));
		int jl=it-q.begin();
		cout << *it;
		m-=jl;
		q.erase(it);
		
	}
	while (!q.empty()){
		cout << q.front();
		q.pop_front();
	}
	return 0;
}
/*
dcba




adcba
adcab
adacb
aadcb

下午

依赖背包
Great Cow Gathering
树形dp 树的重心+最短路
错误原因:2个dfs递归时名字写错
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
struct node{
	long long next,to,len;
}edge[200010];
long long h[200010];
long long tot;
void add(long long x,long long y,long long z){
	tot++;
	edge[tot].to=y;
	edge[tot].len=z;
	edge[tot].next=h[x];
	h[x]=tot;
}
long long sz[200010];
long long mx[200010];
long long c[200010];
long long sum;
void dfs(long long u,long long fa){
	sz[u]=c[u];
	for (int i=h[u];i;i=edge[i].next){
		long long to=edge[i].to;
		if (to==fa){
			continue;
		}
		dfs(to,u);
		sz[u]+=sz[to];
		mx[u]=max(mx[u],sz[to]);
	}
	mx[u]=max(mx[u],sum-sz[u]);
}
void df(long long u,long long fa){
	for (int i=h[u];i;i=edge[i].next){
		long long to=edge[i].to;
		if (to==fa){
			continue;
		}
		sz[to]=sz[u]+edge[i].len;
		df(to,u);
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n;
	cin >> n;
	for (int i=1;i<=n;i++){
		cin >> c[i];
		sum+=c[i];
	} 
	for (int i=1;i<=n-1;i++){
		long long u,v,l;
		cin >> u >> v >> l;
		add(u,v,l);
		add(v,u,l);
	}
	long long cl=1;
	dfs(1,1);
	for (int i=1;i<=n;i++){
		if (mx[i]<mx[cl]){
			cl=i;
		}
	}
	sz[cl]=0;
	df(cl,cl);
	long long ans=0;
	for (int i=1;i<=n;i++){
		ans+=sz[i]*c[i];
	}
	cout << ans;
	return 0;
}
选课
第一种
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int n,m;
int s[310];
int f[310][310];//第二维:刚好m节课(注意边界:能选m节课>=m 否则不合法赋极小值见46行) 
struct node{
	int next,to;
}edge[310]; 
int h[310],tot;
void add(int x,int y){
	tot++;
	edge[tot].to=y;
	edge[tot].next=h[x];
	h[x]=tot;
}
void dfs(int u){
	f[u][1]=s[u];
	for (int i=2;i<=m;i++){
		f[u][i]=-(1<<30);//赋初值  
	}
	for (int i=h[u];i;i=edge[i].next){
		int to=edge[i].to; 
		dfs(to);//先算清楚再转移 
		for (int j=m;j>=2;j--){
			for (int k=1;k<j;k++){//留一门课给根 
				f[u][j]=max(f[u][j],f[u][j-k]+f[to][k]);
			}
		}
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	/*森林/树 
	f[i][j]以i为根的子树内分配k门课,问最大学分 
	枚举1个儿子,将j-1门课其中k门给这棵子树
	f[i][j]=max(f[i][j-k],f[v][k]);(j-k>=1)(枚举儿子v) 留一节课给父节点(根) 
	f[i][1]=s[i]
	f[i][0]=0
	状态个数O(nm*m)
	森林->树(超级根,以原来树根为儿子) 
	超级先修课->超级根,0分,m+1门课 
	
	cin >> n >> m;
	m++;
	for (int i=1;i<=n;i++){
		int k; 
		cin >> k >> s[i];
		add(k,i);
	}
	dfs(0);
	cout << f[0][m];
	return 0;
}
第二种
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int n,m;
int s[310];
int f[310][310];//第二维:刚好m节课(注意边界:能选m节课>=m 否则不合法赋极小值见46行) 
struct node{
	int next,to;
}edge[310]; 
int h[310],tot;
int siz[310],lis[310],cnt; 
void add(int x,int y){
	tot++;
	edge[tot].to=y;
	edge[tot].next=h[x];
	h[x]=tot;
}
void dfs(int u){
	siz[u]=1;
	lis[++cnt]=u;
	for (int i=h[u];i;i=edge[i].next){
		int to=edge[i].to;
		dfs(to);
		siz[u]+=siz[to];
	} 
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	/*
	1.
	森林/树 
	f[i][j]以i为根的子树内分配k门课,问最大学分 
	枚举1个儿子,将j-1门课其中k门给这棵子树
	f[i][j]=max(f[i][j-k],f[v][k]);(j-k>=1)(枚举儿子v) 留一节课给父节点(根) 
	f[i][1]=s[i]
	f[i][0]=0
	状态个数O(nm*m)
	森林->树(超级根,以原来树根为儿子) 
	超级先修课->超级根,0分,m+1门课 

	
	2.
	f[i][j]:考虑将最多j门课分配给DFS序在第i~n之间的课程中,获取的最大学分 
	f[i][j]=max(s[list[i]]+f[i+1][j-1],f[i+s[list[i]]][j]);
	(i:n~1);
	ans=f[1][m]
	
	cin >> n >> m;
	m++;
	for (int i=1;i<=n;i++){
		int k; 
		cin >> k >> s[i];
		add(k,i);
	}
	dfs(0);
	n++;
	for (int i=n;i>=1;i--){
		for (int j=1;j<=m;j++){
			f[i][j]=max(s[lis[i]]+f[i+1][j-1],f[i+siz[lis[i]]][j]);
		}
	}
	cout << f[1][m];
	return 0;
}
01广搜
Wizard in Maze
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
char a[1010][1010];
int js[1010][1010];
int h,w;
int sc,sr;
int ec,er;
deque<pair<int,int>> q;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int ax[]={0,0,0,0,1,1,1,1,1,2,2,2,2,2,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2};
int ay[]={-2,-1,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2};
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> h >> w;
	cin >> sc >> sr;
	cin >> ec >> er;
	for (int i=1;i<=h;i++){
		for (int j=1;j<=w;j++){
			cin >> a[i][j];
		}
	}
	memset(js,0x3f,sizeof(js));
	js[sc][sr]=0;
	q.push_back({sc,sr});
	while (!q.empty()){
		pair<int,int> p=q.front();
		q.pop_front();
		if (p.first==ec && p.second==er){
			cout << js[ec][er];
			return 0;
		}
		for (int i=0;i<4;i++){
			int xx=dx[i]+p.first,yy=dy[i]+p.second;
			if (xx<1 || xx>h || yy<1 || yy>w || a[xx][yy]=='#'){
				continue;
			}
			if (js[xx][yy]>js[p.first][p.second]){
				js[xx][yy]=js[p.first][p.second];
				q.push_front({xx,yy});
			}
		}
		for (int i=0;i<24;i++){
			int xx=p.first+ax[i],yy=p.second+ay[i];
			if (xx<1 || xx>h || yy<1 || yy>w || a[xx][yy]=='#'){
				continue;
			}
			if (js[xx][yy]>js[p.first][p.second]+1){
				js[xx][yy]=js[p.first][p.second]+1;
				q.push_back({xx,yy});
			}
		}
	} 
	cout << -1;
	return 0;
}
石子合并 线性
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int a[310];
long long s[310];
long long dp[310][310];
long long ddp[310][310];
int main(){
	int n;
	cin >> n;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	}
	for (int i=1;i<=n;i++){
		s[i]=s[i-1]+a[i];
	}
	memset(dp,0x3f,sizeof(dp));
	memset(ddp,-0x3f,sizeof(ddp));
	for (int len=1;len<=n;len++){
		for (int l=1;l+len-1<=n;l++){
			int r=l+len-1;
			if (len==1){
				dp[l][r]=0;
				ddp[l][r]=0;
			}
			else{
				for (int k=l;k<r;k++){
					dp[l][r]=min(dp[l][k]+dp[k+1][r]+s[r]-s[l-1],dp[l][r]);
					ddp[l][r]=max(ddp[l][k]+ddp[k+1][r]+s[r]-s[l-1],ddp[l][r]);
				}
			}
		}
	}
	cout << dp[1][n] << endl;
	cout << ddp[1][n];
	return 0;
}
248
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long a[300];
long long dp[300][300];
int main(){
	int n;
	cin >> n;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	}
	memset(dp,-0x3f,sizeof(dp));
	for (int len=1;len<=n;len++){
		for (int l=1;l+len-1<=n;l++){
			int r=l+len-1;
			if (len==1){
				dp[l][r]=a[l];
			}
			else{
				for (int k=l;k<r;k++){
					if (dp[l][k]==dp[k+1][r]){
						dp[l][r]=max(dp[l][r],dp[l][k]+1);
					}
				}
			} 
		}
	}
	long long maxx=INT_MIN;
	for (int i=1;i<=n;i++){
		for (int j=1;j<=n;j++){
			maxx=max(maxx,dp[i][j]);
		}
	}
	cout << maxx;
	return 0;
}

晚上

模拟赛3
小杨的空调温度调整
小杨爱整数
冰冻阵法

DAY 4

上午

讲解比赛题目
小杨的空调温度调整
差分
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long p[100010];
long long t[100010];
long long c[100010];
long long b[100010];
long long v[100010];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n;
	cin >> n;
	for (int i=1;i<=n;i++){
		cin >> p[i];
	} 
	for (int i=1;i<=n;i++){
		cin >> t[i];
	}
	long long sum=0;
	for (int i=1;i<=n+1;i++){
		b[i]=p[i]-p[i-1];
		c[i]=t[i]-t[i-1]; 
		v[i]=b[i]-c[i];
		if (v[i]>0){
			sum+=v[i];
		}
	}
	cout << sum;
	return 0;
} 
小杨爱整数
dp
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long a[110];
long long n;
long long f[110][110]; 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	} 
	//f[p][g]选择p个数时和对i取模=g的方案 
	//a[j]%i->   f[p][g]+=f[p-1][(g-a[j])%i];
	//ans=f[i][0];
	long long ans=0;
	for (int i=1;i<=n;i++){
		memset(f,0,sizeof(f));
		f[0][0]=1;
		for (int j=1;j<=n;j++){
			for (int p=i;p>=1;p--){
				for (int g=0;g<i;g++){
					int lo=(g+a[j])%i;
					f[p][lo]+=f[p-1][g];	
					f[p][lo]%=998244353;
				}
			}
		}
		ans+=f[i][0];
		ans%=998244353; 
	}
	cout << ans;
	return 0;
}
冰冻阵法(尚未AC)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long c[1010],dis[1010],u[1010],w[1010],v[1010];
vector<pair<int,int>> p[1010];
int kl[1010];
int n;
bool lk;
long long minn;
void dfs(int x,long long sum){
	if (x==n+1){
		for (int i=1;i<=n;i++){
			lk=0;
			if (kl[i]==0){
				for (auto j:p[i]){
					if (kl[j.first]==1 && j.second<=dis[j.first]){
						lk=1;
						break;
					}
				}
//				if (lk==0){
//				 	if (kl[3]==1 && kl[4]==0 && kl[1]==0  && kl[5]==0 && kl[2]==0){
//				 		cout << i << "**";
//					} 
//					return;
//				}
			} 
		}
//		if (kl[3]==1 && kl[4]==0 && kl[1]==0  && kl[5]==0){
//			cout << sum << "**";
//		} 
		minn=min(minn,sum);
		return;
	}
	kl[x]=1;
	dfs(x+1,sum+c[x]);
	kl[x]=0;
	dfs(x+1,sum);
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	// f[u][j] :根为u的子树全满足,且使用子树外冰柜为j的情况
	//j>0 真用 1.以v[i]为根的子树自我消化  2.以v[i]为根的子树也用了j
	//j=0,不用 1.以v[i]为根的子树自我消化  2.以v[i]为根的子树用u
	//ans=f[i][0]; 
	int t;
	cin >> t;
	while (t--){
		cin >> n;
		memset(kl,0,sizeof(kl));
		memset(p,0,sizeof(p));
		for (int i=1;i<=n;i++){
			cin >> c[i];
		}
		for (int i=1;i<=n;i++){
			cin >> dis[i];
		}
		for (int i=1;i<=n-1;i++){
			cin >> u[i] >> v[i] >> w[i];
			p[u[i]].push_back({v[i],w[i]});
			p[v[i]].push_back({u[i],w[i]});
		}
		minn=0x3f3f3f3f;
		dfs(1,0);
		cout << minn << endl;
	}
	return 0;
}

DAY 5

上午

图论和树论
换根dp
n个点,选择x集合 求和dis(i,x)(1<=i<=n) min
换根 1.假设一个点为根(1) 算出x=1的情况
  1. 更换树根
树的重心
删除该点后形成的森林中树的最大大小的最小值
树的重心有1个或2个
2个:
2个重心相连 ,且将两个重心分开后树对称
树的重心如果不唯一,则至多有两个,且这两个重心相邻。
以树的重心为根时,所有子树的大小都不超过整棵树大小的一半。
树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么到它们的距离和一样。
把两棵树通过一条边相连得到一棵新的树,那么新的树的重心在连接原来两棵树的重心的路径上。
在一棵树上添加或删除一个叶子,那么它的重心最多只移动一条边的距离。
树的重心 模板题 (1~2个重心)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int n;
vector<int> f[500010];
int maxx;
int sz[500010];
int ol[2];
void dfs(int u,int fa){
	sz[u]=1;
	int mx=0;
	for (auto v:f[u]){
		if (v==fa){
			continue;
		}
		dfs(v,u);
		sz[u]+=sz[v];
		mx=max(mx,sz[v]);
	}
	mx=max(mx,n-sz[u]);
	if (mx<maxx){
		maxx=mx;
		ol[0]=u;
		ol[1]=-1;
	}
	else if (mx==maxx){
		ol[1]=u;
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);  
	cin >> n;
	for (int i=1;i<=n-1;i++){
		int u,v;
		cin >> u >> v;
		f[u].push_back(v);
		f[v].push_back(u);
	}
	maxx=n;
	dfs(1,0);
	if (ol[1]==-1){
		cout << ol[0];
	}
	else{
		cout << min(ol[0],ol[1]) << " " << max(ol[0],ol[1]); 
	}
	return 0;
} 
会议
树的重心模板+计算树上点到重心的最小距离(重心可能有1~2个)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
long long n;
vector<long long> f[500010];
long long maxx;
long long sz[500010];
long long ol[2];
long long kl,u,v;
void dfs(long long u,long long fa){
	sz[u]=1;
	long long mx=0;
	for (auto v:f[u]){
		if (v==fa){
			continue;
		}
		dfs(v,u);
		sz[u]+=sz[v];
		mx=max(mx,sz[v]);
	}
	mx=max(mx,n-sz[u]);
	if (mx<maxx){
		maxx=mx;
		ol[0]=u;
		ol[1]=-1;
	}
	else if (mx==maxx){
		ol[1]=u;
	}
}
queue<long long> q;
long long fg[50010]; 
long long ans;
void bfs(){
	q.push(kl);
	q.push(-1);
	fg[kl]=1;
	long long dep=0;
	while (!q.empty()){
		int p=q.front();
		q.pop();
		if (p==-1){
			dep++;
			if (q.empty()){
				break;
			}
			q.push(-1);
		}
		else{
			for (auto it:f[p]){
				if (fg[it]==0){
					fg[it]=1;
					q.push(it);
				}
			}
			ans+=dep;
		}
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);  
	cin >> n;
	for (int i=1;i<=n-1;i++){
		cin >> u >> v;
		f[u].push_back(v);
		f[v].push_back(u);
	}
	maxx=n;
	dfs(1,0);
	if (ol[1]==-1){
		kl=ol[0];
	}
	else{
		kl=min(ol[0],ol[1]);
	}
	bfs();
	cout << kl << " "<< ans;
	return 0;
}
/*
2 -1
-1 1 3   dep=1;
1 3 -1   dep=1; 
3 -1   dep=1 ans=1
-1 4   dep=1 ans=2;
4 -1   dep=2 ans=2;
-1     dep=2 ans=4

机房
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
const int maxn=100100;
struct node{
	long long next,to;
}edge[maxn*2];
long long f[maxn][22];// 2^20>100000 
long long h[maxn],tot,dep[maxn];
long long n;
long long d[100010];
long long yh[100010];
void add(long long x,long long y){
	tot++;
	edge[tot].to=y;
	edge[tot].next=h[x];
	h[x]=tot;
}
void dfs(long long x,long long fa){
	for (int i=h[x];i;i=edge[i].next){
		long long to=edge[i].to;
		if (to==fa){
			continue;
		}
		dep[to]=dep[x]+1;
		yh[to]=d[to]+yh[x];
		f[to][0]=x; 
		dfs(to,x);
	}
}
long long lca(long long x,long long y){
	if (dep[y]>dep[x]){
		swap(x,y);
	}
//	long long tmp=dep[x]-dep[y];
//	long long tim=0;
//	while (tmp){
//		if (tmp&1){
//			x=f[x][tim];
//		}
//		tim++;
//		tmp>>=1;
//	}
//	for (int i=20;i>=0;i--){
//		if (dep[x]-(1<<i)>=dep[y]){
//			x=f[x][i];
//		}
//	}
	for(int i=18;i>=0;i--){
		if(dep[y]<=dep[f[x][i]]){
			x=f[x][i];
		} 
	}
	if (x==y){
		return x;
	}
	for (int i=18;i>=0;i--){
		if (f[x][i]!=f[y][i]){
			x=f[x][i];
			y=f[y][i];
		}
	}
	if (f[x][0]==0){
		return 1;
	} 
	return f[x][0];
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n,m;
	cin >> n >> m;
	for (int i=1;i<=n-1;i++){
		long long x,y;
		cin >> x >> y;
		add(x,y);
		add(y,x);
		d[x]++; 
		d[y]++;
	} 
	yh[1]=d[1];
	dfs(1,0);
	for (int j=1;j<=18;j++){
		for (int i=1;i<=n;i++){
			f[i][j]=f[f[i][j-1]][j-1];
		//	cout << f[i][j] << " "; 
		}
	}
	for (int i=1;i<=m;i++){
		long long u,v;
		cin >> u >> v;
//		if (u==v){
//			cout << d[u] << endl;
//		}
//		else{
			long long cl=lca(u,v);
			cout << yh[u]+yh[v]-2*yh[cl]+d[cl] << endl;
//		}
	}
	return 0;
}
Anton and Tree
建原树
缩点建新树
求新树直径
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int c[200010];
struct node{
	int next,to;
}edge1[400010],edge2[400010]; 
int h1[200010],tot1;
int h2[200010],tot2;
int n;
int num[200010];
int cnt;//块的个数 
void add1(int x,int y){
	tot1++;
	edge1[tot1].to=y;
	edge1[tot1].next=h1[x];
	h1[x]=tot1;
}
void add2(int x,int y){
	tot2++;
	edge2[tot2].to=y;
	edge2[tot2].next=h2[x];
	h2[x]=tot2;
}
void dfs1(int x,int fa){
	num[x]=cnt;
	for (int i=h1[x];i;i=edge1[i].next){
		int to=edge1[i].to;
		if (to!=fa && c[x]==c[to]){
			dfs1(to,x);
		}
	} 
}
int d[200010];
int ol;
void dfs2(int u,int fa){
	for (int i=h2[u];i;i=edge2[i].next){
		int to=edge2[i].to;
		if (to==fa){
			continue;
		}
		d[to]=d[u]+1;
		if (d[to]>d[ol]){
			ol=to;
		}
		dfs2(to,u);
	}
} 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	//建原树 
	//缩点建新树
	//求新树直径 
	cin >> n;
//	cout << "%%";
	for (int i=1;i<=n;i++){
		cin >> c[i];
	} 
//	cout << "++";
	for (int i=1;i<=n-1;i++){
		int u,v;
		cin >> u >> v;
		add1(u,v);
		add1(v,u);
	}
//	cout << "{{}}";
	for (int i=1;i<=n;i++){
		if (num[i]==0){
			cnt++;
			dfs1(i,0);
	//		cout << "||";
		}
	}
//	cout << "^^";
	//看边是否应该出现在新树中 
	for (int i=1;i<=n;i++){
		for (int j=h1[i];j;j=edge1[j].next){
			int to=edge1[j].to;
			if (num[i]==num[to]){
				continue;
			}
			//i->to
			add2(num[i],num[to]); 
		//	add2(num[to],num[i]);
		}
	}
//	cout << "**";
	dfs2(1,0);//第一次dfs在新的树上找直径 
//	cout << "&&";
	d[ol]=0;
	dfs2(ol,0);//第二次dfs在新的树上找直径 
	//把距离变成操作次数 
	cout << int(ceil(d[ol]*1.0/2));
	return 0;
}
Kay and Snowflake (尚未AC)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	//1.根本身为重心O(N)  去根后子树大小<=1/2(size)树的大小; 
	//2.根本身不为重心O(N)  暴力找重心(范围内)    
	return 0;
}

晚上

模拟赛四 OI赛制
小杨的房屋分配
小杨的符文师职业之旅
波动序列
回文博弈

DAY 6

上午

讲解比赛题目
小杨的房屋分配
错误原因:for循环边界错误(逗号用法不明确导致边界错误,本来能对)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long a[200010],b[200010];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n,m,k;
	cin >> n >> m >> k;
	for (int i=1;i<=n;i++){
		cin >> b[i];
	} 
	for (int j=1;j<=m;j++){
		cin >> a[j];
	}
	sort(b+1,b+n+1);
	sort(a+1,a+m+1);
	long long sum=0;
	//for (int i=1,j=1;i<=n,j<=m;){ 逗号分隔两个语句在中间(判断边界)只有最后一个生效
	//https://chat.deepseek.com/a/chat/s/92f32a73-c097-4bb0-8b9d-d998a2d7238a
	//判断边界同时成立用&& 或者用while() 
	//逗号用于for循环1,3部分(定义赋值和自增自减) 
	for (int i=1,j=1;;){
		if (i>n || j>m){
			break;
		}
		if (b[i]>=a[j]-k && b[i]<=a[j]+k){
			sum++;
			i++;
			j++;
		}
		else if (b[i]<a[j]-k){
			i++;
		}
		else if (b[i]>a[j]+k){
			j++;
		}
	}
	cout << sum;
	return 0;
}
/*
小杨的符文师职业之旅
错误原因:数组开小了(2582行,2592行,2599(原来<=pl)pl>1010越界)应该不用pl数组开1010
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long l[2010],d[2010];
long long dp[2010][2010]; 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n;
	cin >> n;
	//long long pl=0;
	for (int i=1;i<=n;i++){
		cin >> l[i];
	//	pl+=l[i];
	}
	for (int i=1;i<=n;i++){
		cin >> d[i];
	}
	dp[0][0]=0;
	for (int i=1;i<=n;i++){
		for (int j=0;j<=n;j++){
			dp[i][j]=dp[i-1][j];
			if (j>=l[i]){
				dp[i][j]=max(dp[i][j],dp[i-1][j-l[i]]+d[i]); 
			}
		}
	}
	long long maxx=0;
	for (int i=0;i<=n;i++){
		maxx=max(maxx,dp[n][i]);	
	}
	cout << maxx;
	return 0;
}
/*
2 2 1 1 1
7 8 3 3 3

1234512345
8+3+7
以大换小 (比较) 
排序
 
凑和为n,的最大值 

第i个和为j的最大伤害 

波动序列 (尚未AC)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long a[1000010];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n;
	cin >> n;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	} 
//	long long maxx=0;
	long long hj=0;
	for (int i=1;i<=n;i++){
	//	maxx=max(maxx,a[i]-a[i-1]); 
		hj=hj+a[i]-a[i-1];
	}
	//2^31(32正负)   4*10^9(正负)   32/33 21 4748 3647
	//没有单调性 不能二分 
//	long long l=minn,r=maxx,mid=(l+r)/2;
//	while (l<=r){
//		mid=(l+r)/2;
//		
//	}
	hj/=n;
	long long sum=1,mxx=0,ls=0,ol=0;
	if (hj<0){
		hj=0;
	}
	for (int i=0;i<=hj;i++){
		sum=1;
		ls=a[1];
		for (int j=2;j<=n;j++){
			if (a[j]>a[j-1]){
				if (ls+i==a[j]){
					sum++;
				}
				ls+=i;
			}
			else if (a[j]==a[j-1]){
				if (ls==a[j]){
					while (a[j]==a[j-1]){
						sum++;
						j++;
					}
					j--;
				}
			}
			else{
				if (ls-i==a[j]){
					sum++;
				}
				ls-=i;
			}
		}
	//	cout << sum << " " << i << endl;
		if (sum>mxx){
			mxx=sum;
			ol=i;
		}
	}
	cout << mxx << endl;
	cout << ol;
	return 0;
}
/*
1 2 2 2 2 2 4
1 2 2 2 2 2 
回文博弈(尚未AC)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
const int maxn=1000100;
int len[maxn];
 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	/*
	直接是回文 徐输 
	串长奇数
	1.1:串不存在长度>1的回文子串 徐赢 
	1.2:存在长度>1的回文子串 徐赢 
	串长偶数 
	1.1 石老师赢 
	
	字符串回文 
	
	
	int n;
	cin >> n;
	string s;
	cin >> s;
	int q;
	cin >> q;
	bool fg=0;
	len[0]=1;
	int pos=0;
	//奇数 
	for (int i=1;i<s.size();i++){
		//s[i]已经不在之前的基准串里
		if (i>pos+len[pos]/2){
			pos=i;
			len[i]=1;
			while (i>=len[i]/2+1 && s[i-len[i]/2-1]==s[i+len[i]/2+1]){
				len[i]++;
			}
			continue;
		}
		//基准串的中心点是pos 现在要求得是以s[i]为中心的最长回文串
		//求出第二个基准串的中心点
		int j=pos*2-i;
		if (pos-len[pos]/2<j-len[j]/2){//第二个基准串可以完整对称过来 
			len[i]=len[j];
		} 
		else if (pos-len[pos]/2>j-len[j]/2){//只能将第二个基准串处于第一个基准串里面的,且回文的部分进行对称 
			len[i]=2*(j-(pos-len[pos]/2))+1;
		}
		else{
			len[i]=len[j];
			while (i>=len[i]/2+1 && s[i-len[i]/2-1]==s[i+len[i]/2+1]){
				len[i]++;
			}
		}
		//维护第一个基准串
		if (i+len[i]/2>pos+len[pos]/2){
			pos=i;
		} 
	}
	while (q--){
		int l,r;
		cin >> l >> r;
		l--;
		r--;
//		fg=0;
//		for (int i=0;i<=(l+r)/2-l;i++){
//			if (s[i+l]!=s[r-i]){
//				fg=1;
//				break;
//			}
//		}
		if (fg==0){
			cout << "Mr.Shi" << endl;
		}
		else{
			if ((r-l+1)%2==1){
				cout << "Mr.Xu" << endl;
			}
			else{
				cout << "Mr.Shi" << endl; 
			}
		}
	} 
	return 0;
}
/*
asdfdsa
对称截 徐输 
一左一右不对称 ? 
全在左/右 奇偶性(这里只半边没有回文)奇 徐输 偶 石输 

1~3
暴搜
枚举截取
记录最大值(最佳情况)选定一个人记录
边界 回文  输赢 
走最佳路线  选定的人走赢得,另一个走他赢得(选定的输的) 
最后看输赢 

下午

1.KMP
2.manacher
KMP模板
C
https://paste.ubuntu.com/p/94cw4g5fsS/
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
const int maxn=1000100;
string sh,ch;
int fail[maxn]; //fail[i]表示ch串中右端点下标为i的前缀的border的右端点下标
//  特殊的 如果border为空 那么-1 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> sh >> ch;
	fail[0]=-1;
	for (int i=1;i<ch.size();i++){
		//现在在求解右端点下标为i的前缀的border
		//从右端点下标为i-1的前缀的border开始枚举
		//试图加入ch[i] 形成一个新的border
		int j=fail[i-1];
		while (j!=-1){
			if (ch[j+1]==ch[i]){
				break;
			}
			j=fail[j];
		} 
		if (ch[j+1]==ch[i]){
			fail[i]=j+1;
		}
		else{
			fail[i]=-1;
		}
	} 
	int j=-1;
	for (int i=0;i<sh.size();i++){
		while (j!=-1){
			if (ch[j+1]==sh[i]){
				break;
			} 
			j=fail[j];
		}
		if (ch[j+1]==sh[i]){
			j++; 
		}
		else{
			j=-1;
		}
	}
	if (j==ch.size()-1){
		//找到了,可以说明ch是sh的子串 
		//可以说明ch的最后一个字符是和sh[i]匹配的 
	}
	return 0;
}
 
【模板】KMP
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int t[1000010];
int main(){
	string s,p;
    cin >> s >> p;
    int sl=s.size();
    int pl=p.size();
    for (int i=1,j=0;i<pl;i++){
        while (j && p[i]!=p[j]){
        	j=t[j-1];
        } 
        if (p[i]==p[j]){
        	j++;
        }
        t[i]=j;
    }
    for (int i=0,j=0;i<sl;i++){
        while (j && s[i]!=p[j]){
        	j=t[j-1];
        } 
        if (s[i]==p[j]){
        	j++;
        } 
        if (j==pl){
            cout << i-pl+1+1 << endl;
            j=t[j-1];
        }
    }
    for (int i=0;i<p.size();i++){
    	cout << t[i] << " ";
    } 
    return 0;
}
【模板】manacher
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int l[23000010];
int main(){
//	ios::sync_with_stdio(0);
//	cin.tie(0);
//	cout.tie(0);
	string s,t="*";
	cin >> s;
	for (int i=0;i<s.size();i++){
		t+=s[i];
		t+='*';
	}
	l[0]=0;
	int tmp=0,mx=0,ans=0;
	for (int i=1;i<t.size();i++){
		if (i<=tmp+mx){
			int j=tmp*2-i;
			if (tmp-mx<j-l[j]){
				l[i]=l[j];
			}
			else if (tmp-mx>j-l[j]){
				l[i]=j-(tmp-mx);
			}
			else{
				l[i]=l[j];
			}
		}
		while (i>l[i] && t[i-(l[i]+1)]==t[i+(l[i]+1)]){
			l[i]++;
		}
		ans=max(ans,l[i]);
		if (tmp+mx<=i+l[i]){
			tmp=i;
			mx=l[i];
		//	cout << i << " " << l[i] << endl;
		}
	}
	cout << ans;
    return 0;
}
/*
*a*a*a*
Radio Transmission 无线传输
C
#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long 
ull p[1000010];
ull b[1000010];
ull wd(int l,int r){
	return b[r]-b[l-1]*p[r-l+1];
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin >> n;
	string s;
	cin >> s;
	ull k=131;
	p[0]=1;
	for (int i=1;i<=n;i++){
		p[i]=p[i-1]*k;
	}
	b[0]=0;
	for (int i=1;i<=n;i++){
		b[i]=b[i-1]*k+s[i-1];
	}
	bool fg=0;
//	cout << wd(1,3) << endl;
	for (int i=1;i<=n;i++){
		ull t=b[i];
	//	cout << t << " ";
		fg=0;
		for (int j=i;j<s.size();j+=i){
			if (j+i<=s.size()){
				ull l=wd(j+1,j+i);
				if (l!=t){
					fg=1;
				//	cout << s.substr(j,i) << " ";
				//	cout << i << " " << j << " " << l << "* " << endl;
					break;
				}
			}
			else{
				ull m=b[s.size()%i];
				ull o=wd(j+1,s.size());
				if (m!=o){
					fg=1;
				//	cout << i << " " << m << " " << o << "/ " << endl;
					break;
				}
			}
		}
		if (fg==0){
			cout << i;
			return 0;
		}
	}
	return 0;
}
C
#include<bits/stdc++.h>
using namespace std;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	string s1,s2;
	cin >> s1 >> s2;
	string s="";
	int o=0;
	for (int i=0;i<s1.size();i++){
		s+=s1[i];
		if (s2.find(s)<s2.size()){
			o=s.size();
		}
	}
	string ss="";
	int p=0;
	for (int i=0;i<s2.size();i++){
		ss+=s2[i];
		if (s1.find(ss)<s1.size()){
			p=ss.size();
		}
	}
	cout << max(o,p);
	return 0;
}

晚上

模拟赛5
A 数位之和
B gogogo 出发喽
C 抓娃娃机
D 动态队列

DAY 7

上午

数位之和
错误原因:判断条件错误,3633行,原来40分的判断适用于n为负整数(题面不明确)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while (t--){
		int x,y;
		cin >> x >> y;
		int ol=x-y; 
		if (x+1==y){
			cout << "Yes" << endl;
		} 
		else if (x-y<=0){
			cout << "No" << endl;
		} 
		else if ((ol+1)%9==0){
			cout << "Yes" << endl;
		}
		else{
			cout << "No" << endl;
		}
	}
	return 0;
}
gogogo 出发喽
错误原因:状态转移方程错误(人数判断应取最小值3691行)
边界条件错误:总人数>车载最大人数 impossible未判断
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long t[110],z[110];
long long dp[110][110];// i c j r 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n,k,d,T,sum=0;
	cin >> n >> k >> d >> T;
	for (int i=1;i<=k;i++){
		cin >> t[i] >> z[i];
		sum+=z[i];
	}
	memset(dp,0x3f3f3f3f,sizeof(dp));
	dp[0][0]=0;
	for (int i=1;i<=k;i++){
		for (int j=0;j<=n;j++){
			if (dp[i-1][j]!=0x3f3f3f3f){
				dp[i][j]=min(dp[i][j],dp[i-1][j]);
				long long yh=min(z[i],n-j);
				for (int k=1;k<=yh;k++){
					long long fg=j+k;
					long long cv=dp[i-1][j]+d+k*t[i];
					dp[i][fg]=min(dp[i][fg],cv);
				}
			}
		}
	}
//	for (int i=1;i<=k;i++){
//		for (int j=0;j<=n;j++){
//			cout << dp[i][j] << " ";
//		}
//		cout << endl;
//	}
	if (dp[k][n]==0x3f3f3f3f || sum<n){
		cout << "impossible";
	}
	else{
		cout << dp[k][n];
	}
	return 0;
}

下午

Sigma Function
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	for (int i=1;i<=t;i++){
		long long n;
		cin >> n;
		cout << "Case " << i << ": " << n-int(sqrt(n))-int(sqrt(n/2)) << endl;
	} 
	return 0;
}
/*
4 9 16 25 36 49 64 81 

Raising Modulo Numbers
快速幂
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long a[45010],b[45010];
long long ksm(long long n,long long m,long long mod){
	long long ans=1,bs=n;
	while (m!=0){
		if (m&1){
			ans=(bs*ans)%mod;
		}
		bs=bs*bs%mod;
		m>>=1;
	}
	return ans;
} 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long m,n;
	cin >> m >> n;
	long long sum=0;
	for (int i=1;i<=n;i++){
		cin >> a[i] >> b[i];
		long long k=ksm(a[i],b[i],m);
		sum=(sum%m+k)%m;
	}
	cout << sum;
	return 0;
} 
The Euler function
欧拉筛筛欧拉函数
C
#include<bits/stdc++.h>
using namespace std;
const int maxn=30000010;
int isprime[maxn],eular[maxn];
vector<int> prime; 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long a,b;
	cin >> a >> b;
	for (int y=2;y<=b;y++){//y 
		if (isprime[y]==0){
			prime.push_back(y);
			eular[y]=y-1;
		}
		for (auto x:prime){
			if (x*y>b){
				break;
			} 
			isprime[x*y]=1;
			if (y%x==0){
				eular[x*y]=x*eular[y];
				break;
			}
			eular[x*y]=eular[x]*eular[y];
		}
	} 
	long long sum=0;
	for (int i=a;i<=b;i++){
		sum+=eular[i];
	}
	cout << sum;
	return 0;
}

DAY 8

上午

1.费马小定理
若a,p互质,且p是质数,则a的p-1次方mod(%)p=1;
S={1,2,3,······p-1};
T={a,2a,3a······(p-1)a}
将T内每个元素对p取模后构造集合次T 有次T=S
1.T集合内不存在p的倍数
2.T集合内不存在两个元素在模p意义下同余
将S.T集合元素分别相乘
可证费马小定理
2.欧拉定理 (费马小定理特殊形式)
若a,p为两个互质整数,则a的o(p)次方 mod p=1;
o(p)为p的欧拉函数值
令集合S,集合内的任意元素x满足:
  1. 1 ≤ x<p。
  2. gcd(p,x)=1。
乘法逆元
求解 a/b mod p的值 当a,b,特别大时怎末办
考虑将除法运算消除掉。对于 a/b mod p,在取模之前若乘上b的一个倍数,就可以把除法消除。
而为保证取模结果不变,根据乘法的同余定理,乘上的这个数对p取模的结果必须为1。
令满足条件的数为b*k。此时可称k是b关于模p意义下的逆元,当然反过来b也是k关于模p意义下的逆元。
例如,3是2关于模5意义下的逆元。
在求解 a/b mod p 的场景下,我们需要求解b关于模p意义下的乘法 逆元。
其实就是在已知b,p的情况下求解下面这个同余方程: bk ≡ 1 mod p k 的一个正整数解。
这个方程当且仅当gcd(b,p)=1 有解。且有解的时候一定有无数个。 对于乘法逆元的场景,只需要随便得到一个正整数解就行
3 的幂的和(乘法逆元+快速幂)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long gh(long long n,long long a){
	long long ans=1,bs=a;
	while (n!=0){
		if (n&1){
			ans=(bs*ans)%1000000007;
		}
		bs=bs*bs%1000000007;
		n>>=1;
	}
	return ans%1000000007;
} 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n;
	cin >> n;
	n++;
	long long pl=gh(n,3);
	pl-=1;
	pl%=1000000007;
	//pl/=2;
	long long ol=gh(1000000005,2);
	ol%=1000000007;
	cout << pl*ol%1000000007;
	return 0;
}
Sumdiv
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long mod=9901;
long long gh(long long a,long long n){
	long long ans=1,bs=a;
	while (n!=0){
		if (n&1){
			ans=(bs*ans)%mod;
		}
		bs=bs*bs%mod;
		n>>=1;
	}
	return ans%mod;
} 
long long tg(long long p,long long k){
	if (k==0){
		return 1;
	}
	else if (k%2==0){
		return ((1+gh(p,k>>1))*tg(p,(k>>1)-1)+gh(p,k))%mod;
	}
	else{
		return ((1+gh(p,(k+1)>>1))*tg(p,(k-1)>>1))%mod;
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int a,b;
	cin >> a >> b;
	long long ans=1;
	for (int i=2;i<=a;i++){
		long long sum=0;
		while (a%i==0){
			sum++;
			a/=i;
		} 
		if (sum!=0){
			ans=ans*tg(i,sum*b)%mod;
		}
	}
	cout << ans;
	return 0;
}
/*

下午

二项式定理
数学练习:费马小定理 乘法逆元 特殊处理
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long mod=998244353;
long long n;
long long f[100010];
long long x,y;
long long sd(long long a,long long s,long long p){
	long long ans=1; 
	while(s!=0){
		if (s&1){
			ans=ans*a%p;
		}
		a=a*a%p;
		s>>=1;
	}
	return ans%p;
}
long long C(long long m,long long n){
	long long x=sd(f[m]*f[n-m]%mod,mod-2,mod)%mod;
    return f[n]*x%mod;
}
int main(){
    cin >> n;
    long long ans=0;
    f[0]=1;
    for (int i=1;i<=n;i++){
    	f[i]=f[i-1]*i%mod;
	}
    long long mid=n/2;
   	bool fg=0;
    if (n%2==0){
    	fg=1;
	}
	for (int i=1;i<=n-1;i++){
		if (fg==1 && i==mid){
			continue;
		}
		ans=ans+C(i-1,n-2);
		ans%=mod;
	}
   	cout << ans;
    return 0;
}
计算系数:二项式定理
ADCBA
C
#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int a,b,k,n,m;
long long ans=1;
long long kuai(int x,int y){
    if (y==0){
        return 1;
    }
    long long k=kuai(x,y>>1);
    k=k*k%mod;
    if (y&1){
        k=k*x%mod;
    }
    return k;
}
int main(){
    cin >> a >> b >> k >> n >> m;
    ans=kuai(a,n)*kuai(b,m)%mod;
    for (int i=1;i<=n+m;i++){
        ans=ans*i%mod;
    }
    for (int i=1;i<=n;i++){
        ans=ans*kuai(i,mod-2)%mod;
    }
    for (int i=1;i<=m;i++) {
        ans=ans*kuai(i,mod-2)%mod;
    }
    cout << ans;
    return 0;
}
排队(超级加强版)
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long pl[200010];
long long fg[200010];
long long mod=1e9+7;
long long gh(long long a,long long n){
	long long ans=1,bs=a;
	while (n!=0){
		if (n&1){
			ans=(bs*ans)%mod;
		}
		bs=bs*bs%mod;
		n>>=1;
	}
	return ans%mod;
} 
long long C(int n,int m){
	return pl[m]*pl[n-m]%mod*fg[n]%mod;
}
int n,m;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	fg[0]=1;
	for (int i=1;i<200010;i++){
		fg[i]=fg[i-1]*i%mod;
	}
	pl[200009]=gh(fg[200009],mod-2);
	for (int i=200009;i>=1;i--){
		pl[i-1]=pl[i]*i%mod;
	}
	while(cin >> n >> m){
		cout << fg[n]*fg[m]*2%mod*(C(n+3,m)*C(n+1,2)%mod+C(n+1,1)*C(n+2,m-1)%mod)%mod << '\n';
	}
	return 0;
}
字符串
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long pl[2000010];
long long fg[2000010];
long long mod=20100403;
long long gh(long long a,long long n){
	long long ans=1,bs=a;
	while (n!=0){
		if (n&1){
			ans=(bs*ans)%mod;
		}
		bs=bs*bs%mod;
		n>>=1;
	}
	return ans%mod;
} 
long long C(int n,int m){
	return pl[m]*pl[n-m]%mod*fg[n]%mod;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin >> n >> m;
	fg[0]=1;
	for (int i=1;i<2000010;i++){
		fg[i]=fg[i-1]*i%mod;
	}
	pl[2000009]=gh(fg[2000009],mod-2);
	for (int i=2000009;i>=1;i--){
		pl[i-1]=pl[i]*i%mod;
	}
	cout<<((C(n+m,m)-C(n+m,m-1))%mod+mod)%mod;
	return 0;
}
非回文串
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long pl[6201000];
long long fg[6201000];
long long mod=1000000007;
long long gh(long long a,long long n){
	long long ans=1,bs=a;
	while (n!=0){
		if (n&1){
			ans=(bs*ans)%mod;
		}
		bs=bs*bs%mod;
		n>>=1;
	}
	return ans%mod;
} 
long long a[30];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n;
	cin >> n;
	long long jm=n/2;
	string s;
	cin >> s;
	for (int i=0;i<s.size();i++){
		a[s[i]-'a']++;
	}
	fg[0]=1;
	for (int i=1;i<=n+100;i++){
		fg[i]=fg[i-1]*i%mod;
	}
	pl[n+100]=gh(fg[n+100],mod-2);
	for (int i=n+99;i>=0;i--){
		pl[i]=pl[i+1]*(i+1)%mod;
	}
	long long ans=1;
	for (int i=0;i<26;i++){
		ans=ans*(fg[jm]*pl[a[i]/2]%mod*pl[jm-a[i]/2]%mod)%mod*(fg[a[i]]*pl[a[i]/2]%mod*pl[a[i]/2]%mod)%mod*fg[a[i]/2]%mod*fg[a[i]/2]%mod;
		jm-=a[i]/2;
	} 
	cout << ((fg[n]-ans)%mod+mod)%mod;
	return 0;
}
晚上
ACM欢乐赛
一切实力都来源于我们的肚量
密码:youduliang

DAY 9

讲解ACM欢乐赛
ABCDEFGHI均已AC
A
C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll ref = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
        ref = (ref << 1) + (ref << 3) + (ch ^ 48), ch = getchar();
    return ref * f;
}
int main()
{
    cout << "He1lo,World";
    return 0;
}
B
C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll ref = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
        ref = (ref << 1) + (ref << 3) + (ch ^ 48), ch = getchar();
    return ref * f;
}
int main()
{
    int n;
    cin >> n;
    int maxx=0;
    for (int i=1;i<=n;i++){
        int x;
        cin >> x;
        maxx=max(maxx,x);
    }
    cout << maxx;
    return 0;
}
C
C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll ref = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
        ref = (ref << 1) + (ref << 3) + (ch ^ 48), ch = getchar();
    return ref * f;
}
int main()
{

    ll a=read(),b=read();
    cout<<a+b;
    return 0;
}
D
C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll ref = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
        ref = (ref << 1) + (ref << 3) + (ch ^ 48), ch = getchar();
    return ref * f;
}
int main()
{
    int t = read();
    while (t--)
    {
        int k = read(), cnt = 0;
        char ans[20] = {};
        for (int i = 9; i; i--)
            if (k >= i)
                ans[cnt++] = i ^ 48, k -= i;
        reverse(ans, ans + cnt);
        puts(ans);
    }
    return 0;
}
E
C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll ref = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
        ref = (ref << 1) + (ref << 3) + (ch ^ 48), ch = getchar();
    return ref * f;
}
int a[200010];
int b[200010];
int fg[200010];
int main()
{
    int n, x;
    cin >> n >> x;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        b[i] = a[i];
    }
    int op = x;
    int sum = 0;
    while (b[op] != 0 && fg[op] == 0)
    {
        fg[op] = 1;
        sum++;
        op = b[op];
    }
    cout << sum;
    return 0;
}
F
C
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
inline ll read()
{
    ll ref = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
        ref = (ref << 1) + (ref << 3) + (ch ^ 48), ch = getchar();
    return ref * f;
}
long long a[200010];
signed main()
{
    long long n = read(), k = read();
    for (int i = 1; i <= n; i++)
    {
        a[i] = read();
    }
    if (n == 1)
        return printf("%lld", a[1] + k), 0;
    sort(a + 1, a + n + 1);
    long long dis = (n+1)/2, len = 1;
    while (dis + len - 1 < n)
    {	
    	int tmp=k;
		k -= max((ll)0,min(k, (a[dis + len] - a[dis]) * len));
        a[dis] += min(max((ll)0,tmp / len), max((ll)0,a[dis + len] - a[dis]));
        
        len++;
        // cout << a[dis] << ' ' << k << ' ' << len << '\n';
        if (!k)
            return printf("%lld", a[dis]), 0;
    }
    cout << max((ll)0,a[dis] + k / len);
    return 0;
}
G
C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e+5 + 5;
int prime[maxn], cnt;
bool is_prime[maxn];
int num, ans = INT_MAX, duliang;
int a[10], b[10];
inline ll read()
{
    ll ref = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
        ref = (ref << 1) + (ref << 3) + (ch ^ 48), ch = getchar();
    return ref * f;
}
inline int len(int al, int bl)
{
    return min(abs(al - bl), min(al, bl) + 10 - max(al, bl));
}
int length(int number) // 计算num和number之间的距离
{
    int answer = 0;
    int temp = num;
    for (int i = 0; i < 5; i++)
    {
        answer += len(temp % 10, number % 10);
        temp /= 10, number /= 10;
    }
    return answer;
}
int main()
{
    num = read();
    for (int i = 2; i < maxn; i++)
    {
        if (!is_prime[i])
        {
            if (length(i) <= ans)
                ans = length(i), duliang = i;
            prime[cnt++] = i;
        }
        for (int j = 0; i * prime[j] < maxn; j++)
        {
            is_prime[i * prime[j]] = 1;
            if (i % prime[j] == 0)
                break;
        }
    }
    printf("%05d", duliang);

    return 0;
}
H
C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll ref = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
        ref = (ref << 1) + (ref << 3) + (ch ^ 48), ch = getchar();
    return ref * f;
}
int dp[1010];
int a[10];
int main()
{
    int n;
    cin >> n;
    a[1] = 10;
    a[2] = 20;
    a[3] = 50;
    a[4] = 100;
    dp[0] = 1;
    for (int i = 1; i <= 4; i++)
    {
        for (int j = a[i]; j <= n; j++)
        {
            dp[j] += dp[j - a[i]];
        }
    }
    cout << dp[n];
    return 0;
}
I
C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e+5+5;
inline ll read(){
    ll ref=0,f=1;char ch=getchar();
    while (!isdigit(ch)){if (ch == '-') f = -1;ch = getchar();}
    while (isdigit(ch)) ref = (ref << 1) + (ref << 3) + (ch ^ 48), ch = getchar();
    return ref*f;
}
ll a[maxn],sum[maxn],pre[maxn];
int main(){
	ll n=read(),k=read(),temp=0;
	for(int i=0;i<n;i++) sum[a[i]=read()]++;sort(a,a+n);
	for(int i=0;i+1<n;i++) temp+=a[n-1]-a[i];
	if(k>temp) return printf("%lld",a[n-1]+(k-temp)/n),0;
	for(int i=1;i<maxn;i++) pre[i]=pre[i-1]+sum[i]*i,sum[i]+=sum[i-1];
//	puts("----");
	for(int i=maxn-1;i;i--){
		int j=i;
		for(temp=0;j<maxn;j+=i){
			temp+=(sum[j]-sum[j-i])*j-(pre[j]-pre[j-i]);
		}temp+=(sum[maxn-1]-sum[j-i])*j-(pre[maxn-1]-pre[j-i]);
		if(temp<=k) return printf("%lld",i),0;
	}

    return 0;
} 

下午

堆,线段树
堆:完全二叉树
父亲<=儿子 小根堆
儿子<=父亲 大根堆
增 删 查
查:堆顶(根) / 元素个数
线段树 n0=n2+1;
总结点数:2n-1
线段树模板
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
const int maxn=100100;
int sum[maxn*4];
int a[maxn];
int n,m; 
void pushup(int v){
	sum[v]=sum[v<<1]+sum[v<<1|1];
}
void build(int v,int l,int r){
	if (l==r){
		sum[v]=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(v<<1,l,mid);
	build(v<<1|1,mid+1,r);
	pushup(v);
}
void modify(int v,int l,int r,int x,int y){
	if (l==r){
		sum[v]=y;
		return;
	}
	int mid=(l+r)>>1;
	if (x<=mid){
		modify(v<<1,l,mid,x,y);
	}
	else{
		modify(v<<1|1,mid+1,r,x,y);
	}
	pushup(v);
}
int ask(int v,int l,int r,int L,int R){
	if (r<L || R<l){//[l,r],[L,R]不相交 
		return 0; 
	}
	if (L<=l && r<=R){
		return sum[v];
	}
	int mid=(l+r)>>1;
	return ask(v<<1,l,mid,L,R)+ask(v>>1|1,mid+1,r,L,R);
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	}
	build(1,1,n);
	for (int i=1;i<=m;i++){
		int op;
		cin >> op;
		if (op==1){
			int x,y;
			cin >> x >> y;
			a[x]=y;
			modify(1,1,n,x,y);
		}
		else{
			int l,r;
			cin >> l >> r;
			cout << ask(1,1,n,l,r) << endl;
		}
	}
	return 0;
}
合并果子
C
#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int>> q;
int main(){
	ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for (int i=1;i<=n;i++){
    	int x;
    	cin >> x;
    	q.push(x);
	}
	long long sum=0;
	while (q.size()>1){
		long long s=q.top();
		q.pop();
		s=s+q.top();
		q.pop();
		sum=sum+s;  
		q.push(s);
	}
	cout << sum;
	return 0;
}
My Cow Ate My Homework S
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int a[100010];
int minn[100010];
double pj[100010];
int h[100010];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin >> n;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	} 
	minn[n+1]=INT_MAX;
	h[n+1]=0;
	for (int i=n;i>=1;i--){
		h[i]=h[i+1]+a[i];
		minn[i]=min(minn[i+1],a[i]);
		if (n-i!=0){
			pj[i]=(h[i]-minn[i])/(n-i);
		}
	}
//	for (int i=1;i<=n;i++){
//		cout << h[i] << " ";
//	} 
//	cout << endl;
//	for (int i=1;i<=n;i++){
//		cout << minn[i] << " ";
//	} 
//	cout << endl;
//	for (int i=1;i<=n;i++){
//		cout << pj[i] << " ";
//	} 
//	cout << endl;
	int maxx=0,ol=0;
	for (int i=1;i<=n;i++){
		if (pj[i]>maxx){
			maxx=pj[i];
//			ol=i;
		}
	}
	for (int i=1;i<=n;i++){
		if (maxx==pj[i]){
			cout << i-1 << endl;
		}
	}
//	cout << ol-1;
	return 0;
}
Counting Haybale P
C
#include<bits/stdc++.h>
using namespace std;
long long a[200010];
long long t[800010];
long long tag[800010];
long long mi[800010];
void build(long long l,long long r,long long cnt){
	if (l==r){
		t[cnt]=a[l];
		mi[cnt]=a[l];
		return;
	}
	long long mid=(l+r)/2;
	build(l,mid,cnt*2);
	build(mid+1,r,cnt*2+1);
	t[cnt]=t[cnt*2]+t[cnt*2+1];
	mi[cnt]=min(mi[cnt*2],mi[cnt*2+1]);
}
void lz(long long cnt,long long l,long long r){
	if (tag[cnt]!=0){
		long long mid=(l+r)/2;
		tag[cnt*2]+=tag[cnt];
		tag[cnt*2+1]+=tag[cnt];
		t[cnt*2]+=tag[cnt]*(mid-l+1);
		t[cnt*2+1]+=tag[cnt]*(r-mid);
		mi[cnt*2]+=tag[cnt];
		mi[cnt*2+1]+=tag[cnt];
		tag[cnt]=0;
	}
}
void up(long long l,long long r,long long L,long long R,long long cnt,long long k){
	long long mid=(l+r)/2;
	if (L<=l && r<=R){
		tag[cnt]+=k;
		t[cnt]+=(r-l+1)*k;
		mi[cnt]+=k; 
		return;
	}
	lz(cnt,l,r);
	if (mid>=L){
		up(l,mid,L,R,cnt*2,k);
	}
	if (mid<R){
		up(mid+1,r,L,R,cnt*2+1,k);
	}
	t[cnt]=t[cnt*2]+t[cnt*2+1];
	mi[cnt]=min(mi[cnt*2],mi[cnt*2+1]);
}
long long q(long long l,long long r,long long L,long long R,long long cnt){
    long long mid=(l+r)/2,sum=0;
	if (L<=l && r<=R){
		return t[cnt];
	}
	lz(cnt,l,r);
	if (mid>=L){
		sum+=q(l,mid,L,R,cnt*2);
	}
	if (mid<R){
		sum+=q(mid+1,r,L,R,cnt*2+1);
	}
	return sum;
}
long long q2(long long l,long long r,long long L,long long R,long long cnt){
    long long mid=(l+r)/2,sum=LLONG_MAX;
	if (L<=l && r<=R){
		return mi[cnt];
	}
	lz(cnt,l,r);
	if (mid>=L){
		sum=min(sum,q2(l,mid,L,R,cnt*2));
	}
	if (mid<R){
		sum=min(sum,q2(mid+1,r,L,R,cnt*2+1));
	}
	return sum;
}
int main(){
//	freopen("101.in","r",stdin);
	//freopen("101.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n,m;
	cin >> n >> m;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	}
	for (int i=0;i<=400005;i++){
		mi[i]=LLONG_MAX; 
	}
	//memset(mi,0x3f3f3f3f,sizeof(mi));
	build(1,n,1);
	while (m--){
		char op;
		cin >> op;
		if (op=='P'){
			long long x,y,k;
			cin >> x >> y >> k;
		//	for (int i=1;i<=)
			up(1,n,x,y,1,k);
		}
		else if (op=='M'){
			long long x,y;
			cin >> x >> y;
			cout << q2(1,n,x,y,1) << endl;
		}
		else if (op=='S'){
			long long x,y;
			cin >> x >> y;
			cout << q(1,n,x,y,1) << endl;
		}
	}
//	for (int i=1;i<=15;i++){
//		cout << t[i] << " ";
//	}
//	cout << endl;
//	for (int i=1;i<=15;i++){
//		cout << tag[i] << " ";
//	}
	return 0;
}
/*
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4

7 5
3 4 1 7 2 5 8
1 1 5 2
1 1 4 3
2 1 4
2 3 4
2 1 2
最小函数值
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
long long a[10010][5];
long long ok[1000010];
long long yh;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin >> n >> m;
	for (int i=1;i<=n;i++){
		cin >> a[i][1] >> a[i][2] >> a[i][3];
	} 
	for (int x=1;x<=m;x++){
		for (int i=1;i<=n;i++){
			if (yh>1000000){
				break;
			}
			ok[++yh]=a[i][1]*x*x+a[i][2]*x+a[i][3]; 
		}
	}
	sort(ok+1,ok+yh+1);
	for (int i=1;i<=m;i++){
		cout << ok[i] << " "; 
	}
	return 0;
}
晚上
模拟赛6
武术修行之路
魔法大陆的传送网络
斐波那契序列
羊腿切割

DAY 10

上午

讲解模拟赛题目
武术修行之路:记忆化搜索/广搜
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
vector<long long> f[300010]; 
long long t[300010];
long long dp[300010];
long long n;
long long dfs(long long x){
	long long sum=t[x];
	for (auto it:f[x]){
		if (dp[it]==-1){
			sum+=dfs(it);
		}
	}
	dp[x]=sum;
	return sum;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	memset(dp,-1,sizeof(dp));
	for (int i=1;i<=n;i++){
		cin >> t[i];
		long long k;
		cin >> k;
		for (int j=1;j<=k;j++){
			long long x;
			cin >> x;
			f[i].push_back(x); 
		}
	} 
	cout << dfs(n);
	return 0;
}
魔法大陆的传送网络:最大公因数+set去重
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
struct node{
	long long x,y;
}a[510];
//bool cmp(node s1,node s2){
//	if (s1.x!=s2.x){
//		return s1.x<s2.x;
//	}
//	return s1.y<s2.y;
//}
long long gcd(long long a,long long b){
	a=abs(a);
	b=abs(b); 
	if (b==0){
		return a;
	}
	return gcd(b,a%b);
}
set<pair<long long,long long>> s; 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n;
	cin >> n;
	for (int i=1;i<=n;i++){
		cin >> a[i].x >> a[i].y;
	}
	for (int i=1;i<=n;i++){
		for (int j=1;j<=n;j++){
			if (i!=j){
				long long dx=a[i].x-a[j].x;
				long long dy=a[i].y-a[j].y;
				long long g=gcd(dx,dy);
				if (g!=0){
					dx/=g;
					dy/=g;
					if (dx!=0){
						if (dx<0){
							dx=-dx;
							dy=-dy;
						}
					}
					else{
						if (dy<0){
							dy=-dy; 
						}
					}
				}
				s.insert({dx,dy});
			}
		}
	}
	cout << s.size()*2;
	return 0;
}

下午:

单调队列+字典树
单调队列模板
C
#include<bits/stdc++.h>
using namespace std;
deque<int> dq;
int a[2000010];
int main(){
	ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n,m;
	cin >> n >> m;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	}
	cout<< 0 << endl;
	for (int i=1;i<n;i++){
		while (!dq.empty() && a[i]<a[dq.back()]){
			dq.pop_back();
		}
		if (!dq.empty() && i-dq.front()>=m){
			dq.pop_front();
		}
		dq.push_back(i);
		cout << a[dq.front()] << '\n';
	}	
	return 0;
}
区间内的最小值
C
#include<bits/stdc++.h>
using namespace std;
deque<int> dq;
int a[2000010];
int main(){
	ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n,m;
	cin >> n >> m;
	for (int i=1;i<=n;i++){
		cin >> a[i];
	}
	cout<< 0 << endl;
	for (int i=1;i<n;i++){
		while (!dq.empty() && a[i]<a[dq.back()]){
			dq.pop_back();
		}
		if (!dq.empty() && i-dq.front()>=m){
			dq.pop_front();
		}
		dq.push_back(i);
		cout << a[dq.front()] << '\n';
	}	
	return 0;
}
[HNOI2003] 操作系统
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int n,sum,ik;
struct node{
	int id,t,s,x;
	friend bool operator < (const node&x,const node&y){
		if (x.x!=y.x){
			return x.x<y.x;
		}
		return x.t>y.t;
	}
}a[10000010];
priority_queue<node> q;
int il(int x,int y){
	return x<y?x:y;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	while (cin >> a[n+1].id >> a[n+1].t >> a[n+1].s >> a[n+1].x){
		n++;
	}
	a[n+1].t=0x3f3f3f3f;
	for (int i=1;i<=n;i++){
		q.push(a[i]);
		ik=a[i].t;
		while (!q.empty() && ik<a[i+1].t && sum<n){
			node tmp=q.top();
			q.pop();
			int w=il(tmp.s,a[i+1].t-ik);
			tmp.s-=w;
			ik+=w;
			if (!tmp.s){
				cout << tmp.id << " " << ik << endl;
				sum++;
			}
			else{
				q.push(tmp);
			}
		}
	}
	return 0;
}
Secret Message G
C
#include<bits/stdc++.h>
using namespace std;
struct node{
	long long ol[2];
	long long fg;
	long long end;
}s[5000010];
long long tot=1,cs=1;
long long n,m,t,num;
void build(const vector<int>& ol){
	cs=1;
	for (int it:ol){
		if (s[cs].ol[it]==0){
			s[cs].ol[it]=++tot;
		}
		cs=s[cs].ol[it];
		s[cs].fg++;
	}	
	s[cs].end++;
}
long long q(const vector<int>& ol){
	cs=1;
	num=0;
	for (int i=0;i<ol.size();i++){
		int ed=ol[i];
		if (s[cs].ol[ed]==0){
			return num;
		}
		cs=s[cs].ol[ed];
		if (s[cs].end>0){
			num+=s[cs].end;
		}
	}
	num+=s[cs].fg-s[cs].end;
	return num;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> m >> n;
	for (int i=1;i<=m;i++){
		long long x,y;
		cin >> x;
		vector<int> ol; 
		while (x--){
			cin >> y;
			ol.push_back(y);
		}
		build(ol);
	}
	for (int i=1;i<=n;i++){
		long long x,y;
		cin >> x;
		vector<int> ol; 
		while (x--){
			cin >> y;
			ol.push_back(y);
		}
		cout << q(ol) << endl;
	}
	return 0;
}
Karuta
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
string s[500010];
int main() {
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
    int n;
    cin >> n;
    for (int i=0;i<n;i++){
    	cin >> s[i];
	}
	vector<pair<string,int>> ol;
    for (int i=0;i<n;i++){
    	ol.push_back({s[i],i});
	}
	vector<int> lcp(n-1);
    sort(ol.begin(),ol.end());
    for (int i=0;i<n-1;i++){
    	const string &a=ol[i].first;
        const string &b=ol[i+1].first;
    	int len=min(a.size(),b.size());
    	int j=0;
    	while (j<len && a[j]==b[j]){
    		j++;
		}
		lcp[i]=j;
	}
	vector<int> yu(n);
 	for (int i=0;i<n;i++){
 		int maxx=0;
 		if (i>0){
 			maxx=max(maxx,lcp[i-1]);
		}
		if (i<n-1){
			maxx=max(maxx,lcp[i]);
		}
		yu[ol[i].second]=maxx;
	}
	for (int i=0;i<n;i++){
		cout << yu[i] << endl;
	}
    return 0;
}

晚上

Ha了咯World
餐馆
定向机器人

DAY 11

上午

讲解模拟赛题目
Ha了咯 World
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while (t--){
		int n,k,p;
		cin >> n >> k >> p;
		if (k==0){
			cout << 0 << endl;
		} 
		else if (n*p<abs(k)){
			cout << -1 << endl;
		}
		else{
			k=abs(k);
			if (k%p==0){
				cout << k/p << endl;
			}
			else{
				cout << k/p+1 << endl;
			}
		}
	}
	return 0;
}
餐馆
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
struct node{
	long long x,y;
}a[200010];
bool cmp(int a,int b){
	return a>b;
}
long long s[200010];
long long pl[200010];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while (t--){
		int n;
		cin >> n;
		for (int i=1;i<=n;i++){
			cin >> a[i].x;
		}
		for (int i=1;i<=n;i++){
			cin >> a[i].y;
		}
		for (int i=1;i<=n;i++){
			s[i]=a[i].y-a[i].x;
		}
		sort(s+1,s+n+1,cmp);
		int qd=1,jz=n;
		int sum=0;
		while (qd<jz){
			if (s[qd]+s[jz]<0){
				jz--;
			}
			else{
				qd++;
				jz--;
				sum++;
			}
		}
		cout << sum << endl;
	} 	
	return 0;
}
/*

8 3 9 2 4 5
5 3 1 4 5 10

3 0 8 -2 -1 -5

下午

初赛讲解
C
#include<bits/stdc++.h>
const double PI=acos(-1.0);
using namespace std;
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		sum=sum*10+ch-48;
		ch=getchar();
	}
	return sum*f;
}
void print(int x){
	if (x<0){
		putchar('-');
		x=-x;
	}
	if (x>9){
		print(x/10);
	}
	putchar(x%10+48);
	return;
}
class ABC{
	public://类似于struct里面的成员权限
		ABC(int A=0,int B=0) :a(A),b(B){
			cout << "ffrhttd\n"; 
//			a=A;
//			b=B;
		} 
//		~ABC(){//删除操作 
//			cout << "ewef";
//		} 
		int a; 
		int getA(){
			return a;
		}
		int getB(){
			return b;
		}
		virtual int getnum(){//虚函数 
			return a*b;
		}
	private://里面的成员只能在类ABC内被访问
		int b; 
	
	protected://里面的成员只会在类ABC和ABC的子类内被访问 
	
};
class ABCD : public ABC{//ABC的子类 
	public:
		ABCD (int A=0,int B=0,int C=0) : ABC(A,B),c(c){
			cout << "ddcdfsg\n";
		} 
		int getnum(){//多态 
			return a*c;
		}
		int getBB(){
			return b; 
		} 
	private:
		int c;
};
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	ABCD p3(1,2,3);
	cout << p3.getnum();
	ABC p1(1,2);
	cout << p1.getnum(); 
	return 0;
}
2025 6月gesp6级
哈夫曼编码
格雷码
2024 12月gesp6级

晚上

2025 6月 gesp7级

DAY 12

上午

2024 12月gesp7级
做CSP2023提高组第一轮洛谷有题

下午

2024 csp-s 完善程序
2023 csp-s 完善程序
拓扑排序

晚上

讲解CSP2023提高组第一轮洛谷有题
Linux命令行
文件/目录
目录
CPP
  1.切换 cd 根目录

		cd.. 上一层
		cd 目录名 1.绝对路径 2.访问下一层
  2.建立/删除/查看
        mkdir/rm/ls
文件
CPP
  新建 touch
  打开方式 比如(code/vim) +文件名 
  rm:删除

DAY 13

上午

讲解CSP-S 2022初赛真题

下午

讲解CSP-S 2022初赛真题 完善程序
讲解CSP-S 2021完善程序
讲解CSP-S 2020完善程序
lowbit(x): 二进制下表示最低位的1

晚上

初赛模拟赛1 69分 估分34

DAY 14

上午

讲解初赛模拟赛1

下午

初赛模拟赛2 73 估分18

晚上

讲解初赛模拟赛2

DAY 15

上午

讲解初赛模拟赛2

下午

讲解线段树区间修改
之前的内容: 线段树

下午

模拟赛3 82.5

晚上

**讲解模拟赛3 **

DAY 16

上午

讲解模拟赛3

评论

0 条评论,欢迎与作者交流。

正在加载评论...