2024复赛集训补题报告5

前言

heiheiheiheihei hahhahahahhahhahhhh,

OK又是大毒瘤但是嘿嘿嘿嘿嘿

第一题牛奶(milk)

题目描述

每天一杯奶,健壮切题人。

Meowowco 有每天喝牛奶的习惯,因为牛奶是膳食中蛋白质、钙、磷、维生素 A、维生素 D 和维生素 B2 的重要来源之一,可以让经常出勤的 Meowowco 变得健壮。因此她每个月都会去买一些牛奶屯在冰箱里。

今天又到了采购的日子,Meowowco 又来到了熟悉的超市,看着冰箱里陈列着价格不同的牛奶,她摸了摸自己的钱包,

“糟糕,出勤花了太多的钱了。。。。。。”

不过这都不是问题,毕竟又不是把所有钱都花完了,只是预算被压缩了。现在问题来了,冰箱里有 nn 个种类的牛奶,它们有各自的数量 aia​i​​ 和价格 bib​i​​。作为一只学过动态规划的猫,Meowowco 一个月需要 mm 盒牛奶,她想知道屯够一个月的牛奶量的最小开销。

输入描述

第一行二个整数 n,mn,m,表示牛奶的种类和牛奶需求量。

接下来 nn 行,每行两个整数 ai,bia​i​​,b​i​​,表示第 ii 种牛奶的数量(盒),和这种牛奶的单价(元)。

保证超市里牛奶的数量大于等于 Meowowco 的需求,即保证 ∑ai≥m∑a​i​​≥m。

输出描述

包含一个整数,表示 Meowowco 采购所需的牛奶所要的最小费用。

输入样例

5 100

20 5

40 9

10 3

80 8

30 6

输出样例

630

样例解释

10×3+20×5+30×6+40×8=30+100+180+320=63010×3+20×5+30×6+40×8=30+100+180+320=630,即售价为 33、55、66 的牛奶全部购入,售价为 88 的牛奶购入 4040 盒。

数据范围

对于 50%50% 的数据:1≤n≤103,1≤m≤1031≤n≤10​3​​,1≤m≤10​3​​。

对于另外 50%50% 的数据:1≤n≤105,1≤m≤1051≤n≤10​5​​,1≤m≤10​5​​。

对于所有的数据一定满足:1≤ai≤100,1≤bi≤1051≤a​i​​≤100,1≤b​i​​≤10​5​​。

测试样例下载

milkicon-default.png?t=O83Ahttps://kdyfiles.oss-cn-hangzhou.aliyuncs.com/kdycec0be6d189d4770b0e7903c6dacd24b.zip

解释 

很简单不多说了直接上代码

代码

#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>	
#include<map>
#include<utility>
#include<cstdlib>
#define ll long long
#define pii pair<long long,long long>
#define endl "\n" 
using namespace std;
pair<int,int> a[100005];
int n,m,cnt,ans;
int main(){
	//freopen("milk.in","r",stdin);
	//freopen("milk.out","w",stdout);
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>a[i].second>>a[i].first;
	}
	int i=0;
	sort(a,a+n);
	while(cnt<m){
		cnt+=a[i].second;
		ans+=a[i].second*a[i].first;
		while(cnt>m){
			cnt-=1;
			ans-=a[i].first;
			
		}
		i++;
	}
	cout<<ans;
    return 0;
}

第二题树组(Traary)

题目描述

树组(Traary)是有序的树序列。

树组把树按有序的形式组织起来的一种形式。

这些有序排列的树的集合称为树组。

。。。。。。

Meowowco 有 nn 棵树苗,今天要在数组的每一个位置种(物理)上一棵树。种好之后,我们称它为树组。

最开始,树组中所有的树的高度为 00。每天过后,每棵树会自然生长 11 单位高度。

Meowowco 的种树过程持续 mm 天,在每一天早上,她有三种操作:

op=1op=1:选择某棵树 xx 对其施展魔法,该效果持续 kk 天(包括当天)。拥有魔法效果的树每天晚上会额外生长 11 单位高度。若施展时该树已经存在魔法效果,则覆盖原来的魔法效果(也就是取消原来的魔法效果,加上这次的魔法效果)。

op=2op=2:选择取消某棵树 xx 的魔法效果,可能会对没有施加魔法的树进行操作。

op=3op=3:Meowowko 想知道该天某棵树 xx 的高度。

对于每个 op=3op=3,输出一个整数 hh,代表该树的高度。

输入描述

第一行输入两个整数 n,m,kn,m,k。

接下来 mm 行,第 ii 行输入格式为 op,x,op∈1,2,3,1≤x≤nop,x,op∈1,2,3,1≤x≤n,代表第 ii 天的操作。

输出描述

对于每个 op=3op=3,输出一行一个整数 hh,代表该树的高度。

输入样例

7 9 3

3 1

3 1

1 5

1 5

1 1

3 1

2 1

3 1

3 5

输出样例

0

1

6

9

12

数据范围

对于 25%25% 的数据:1≤n≤1000,1≤m≤1000,1≤k≤1001≤n≤1000,1≤m≤1000,1≤k≤100。

对于另外 25% 的数据:1≤n≤105,1≤m≤105,1≤k≤1001≤n≤10​5​​,1≤m≤10​5​​,1≤k≤100。

对于另外 50%50% 数据:1≤n≤105,1≤m≤105,1≤k≤1051≤n≤10​5​​,1≤m≤10​5​​,1≤k≤10​5​​。

测试样例下载

测试样例icon-default.png?t=O83Ahttps://kdyfiles.oss-cn-hangzhou.aliyuncs.com/kdy7a40fae024474242ac1f7abb9347b036.zip

解释 

本题还算简单,但是非常容易时间超限,不能用嵌套循环

代码

#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>	
#include<map>
#include<utility>
#include<cstdlib>
#define ll long long
#define pii pair<long long,long long>
#define endl "\n" 
using namespace std;
int n,m,k,day,f[100005],g[100005],h[100005];
void over(int x){
	if(g[x]==0) return ;
	if(f[x]+g[x]-1<=day){
		h[x]+=g[x];
		g[x]=0;
	}
	else{
		int tmp=f[x]+g[x]-1-day;
		h[x]+=day-f[x]+1;
		g[x]=tmp;
		f[x]=day+1;
	}
}
int main(){
	//freopen("traary.in","r",stdin);
	//freopen("traary.out","w",stdout);
	cin>>n>>m>>k;
	while(m--){
		int op,x;
		cin>>op>>x;
		if(op==1){
			over(x);
			f[x]=day+1,g[x]=k;
		}
		else if(op==2){
			over(x);
			g[x]=0;
		}
		else{
			over(x);
			cout<<h[x]+day<<endl;
		}
		day++;
	}
    return 0;
}

第三题智乃的兔子(usagi)

题目描述

Chino 是一个可爱的初中生,超喜欢兔子 (和 Cocoa) …!?精通咖啡,并且能干可靠。

今天 Chino 在梦境世界中被可爱的兔子环绕,它们都是这个梦境世界的卡密——Cocoa 的使徒。每一只棉花糖般的兔子都有一个可爱值 aia​i​​。

“超想和可爱的小兔子们贴贴 ∼∼”

因此她向 Cocoa 许愿:请让我挑选出一些可爱的兔子。

但是,Cocoa 并不希望 Chino 随意挑选兔子,她希望 Chino 挑选出的兔子的可爱值的和是 77 的倍数。Cocoa 作为这个世界的卡密,觉得仅有这一条挑选规则会让游戏变得很无趣,她制定规则的目的,很可能是,吃掉 Chino…!?于是她又增加了一条规则:

Cocoa 亲吻了所有的兔子,它们都受到了”祝福”,当 Chino 选择这只兔子之后,她将会获得祝福值 bib​i​​。当 Chino 拥有的祝福值超过 HH 点时,会被 Cocoa 吃掉。

Chino 想知道怎么样才能完成挑选可爱值和为 77 的倍数的兔子,可爱和最大的同时还不会被吃掉。

输入描述

第一行包含两个正整数 nn 和 HH。

第二行包含 nn 个非负整数 aia​i​​,表示每只兔子的可爱值。

第二行包含 nn 个非负整数 bib​i​​,表示每只兔子的祝福值。

输出描述

输出单行,包含一个整数 SS,表示挑选可爱值和为 77 的倍数的兔子,且不会被吃掉的最大可爱值和。

输入样例1

10 10

9 3 7 3 6 4 4 5 9 9

0 1 1 1 1 0 0 1 0 0

输出样例1

56

输入样例2

3 10

4 3 4

6 5 5

输出样例2

7

数据范围

对于测试点 11∼55:1≤n≤20,H=201≤n≤20,H=20。

对于测试点 66∼1010:1≤n≤100,1≤H≤1001≤n≤100,1≤H≤100。

对于前 50%50% 的数据:1≤ai≤104,0≤bi≤101≤a​i​​≤10​4​​,0≤b​i​​≤10。

对于测试点 1111∼1515:1≤n≤10000,H=9982443531≤n≤10000,H=998244353。

对于测试点 1616∼2020:1≤n≤10000,1≤H≤10001≤n≤10000,1≤H≤1000。

对于 100%100% 的数据:1≤ai≤109,0≤bi≤101≤a​i​​≤10​9​​,0≤b​i​​≤10。

测试样例下载

测试样例icon-default.png?t=O83Ahttps://kdyfiles.oss-cn-hangzhou.aliyuncs.com/kdy7f3543bbf80c43df858e1d053af3a7f6.zip

解释

sub1
对于前 的数据,可以通过枚举
sub2
01背包增加限制:挑选可爱值和为7的倍数。
设 f(i,j,k) :表示前 个物品,空间剩余 ,价值 为 。也就是在 01背包 的基础上多一层关于 的转移。
但是本题需要注意初始化,例如: f(0,0,1) 是一定不合法的,需要初始化为负无穷,其余类似情况都需要清空。
方程:

代码

#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<utility>
#include<cstdlib>
#define ll long long
#define pii pair<long long,long long>
#define endl "\n"
using namespace std;
ll n,H,a[10005],b[10005];
ll f[2][7],dp[2][1005][7];
int main() {
	//freopen("usagi.in","r",stdin);
	//freopen("usagi.out","w",stdout);
	cin>>n>>H;
	for(int i=1; i<=n; i++) {
		cin>>a[i];
	}
	for(int i=1; i<=n; i++) {
		cin>>b[i];
	}
	if(H==998244353){
		memset(f,-0x3f,sizeof(f));
		f[0][0]=0;
		for(int i=1;i<=n;i++){
			int t=i&1;
			for(int j=0;j<7;j++){
				f[t][j]=max(f[t^1][j],f[t^1][((j-a[i]%7)+7)%7]+a[i]);
			}
		}
		cout<<f[n&1][0]<<endl;
		return 0;
	}
	memset(dp,-0x3f3f,sizeof(dp));
	dp[0][0][0]=0;
	for(int i=1;i<=n;i++){
		int t=i&1;
		for(int j=0;j<=H;j++){
			for(int k=0;k<7;k++){
				if(j<b[i]) dp[t][j][k]=dp[t^1][j][k];
				else dp[t][j][k]=max(dp[t^1][j][k],dp[t^1][j-b[i]][((k-a[i])%7+7)%7]+a[i]);
			}
		}
	}
	ll ans=0;
	for(int i=0;i<=H;i++){
		ans=max(ans,dp[n&1][i][0]);
	}
	cout<<ans;	
	return 0;
}

第四题一颗成熟的奥术飞弹(missiles)

题目背景

奥术飞弹是一个非指向性的技能,在施法前可以指定弹道,并对路径上第一个碰撞的目标造成伤害。

作为一颗成熟的奥术飞弹,你应该学会自己决定用于攻击目标的最短路径,并且 100%100% 命中目标。

题目描述

Meowowco 正在玩一款未知的 1V11V1 RTS 游戏,游戏创建后会随机创建一个有 nn 个房间的地图,由 mm 条通道相连,房间与房间之间最多只有一个通道,直接由通道相连的房间的距离可以记为 11,整张地图所有房间两两可达。

Meowowco 出生在编号为 11 的房间,而她的对手出生在编号为 nn 的房间。现在 Meowowco 需要创造军队或者释放技能去击败对手,不过今天她有着更高级的黑魔法加持(指自瞄),令”奥术飞弹”变成”成熟的奥术飞弹”,只释放”奥术飞弹”就可以获得胜利。

作为一颗成熟的奥术飞弹,不管当前处于哪个房间,都会瞬间规划好 一条 前往目标所在位置的最短飞行弹道(当然,最短飞行弹道有时候并不是唯一的,所以有多条最短飞行弹道时会随机选择一条),如果它没有沿着当前房间规划好的最短飞行弹道飞行,记为偏离轨迹 11 次。

作为一颗成熟的奥术飞弹,应该会自己计算一条有着“大可能性“的飞行弹道。由于有些房间的最短飞行弹道不唯一,飞行弹道可能偏离也可能不偏离,”大可能性”飞行弹道要求 可能产生的偏离数尽可能大

一个房间如果有多条通往目标的最短飞行弹道,则可能偏离数增加 11,目标是找到有最多这样房间的飞行弹道。

下面将举个栗子来解释它:

对这个地图来说:

image-20240918174721172

它有 3 条从 1 到 6的最短飞行弹道:

假如你现在处于房间 11,那么你可以选择房间 22 和房间 33 ,因为 22 和 33 都在最短飞行弹道上,所以不管前往哪个房间都会让可能偏离数增加,此时可能偏离数为 11;

当飞弹选择 11=>22 时,接下来它只能沿着 22 => 44 => 66,飞行,因此这条弹道的可能偏离数为 11。

当飞弹选择 11 => 33 时,接下来的房间 44 和 55 都处于最短飞行弹道上,不管前往哪个房间都会让可能偏离数增加,此时可能偏离数增加到 22;之后都只有一条弹道到达 66,因此这两条弹道的可能偏离数为 22。

综上所述,

最大的可能偏离数为 22。

寻找出所有的最短飞行弹道,每条最短飞行弹道都有一个可能偏离数,找到其中最大的可能偏离数,输出最短飞行弹道条数和最大的可能偏离数。


简而言之,就是 nn 个点的无向连通图,无重边和自环,目标是从 11 点到达 nn 点。在一个点上,如果有多条最短路径到达终点,则 可能偏离数 加一,求出最短路径的总条数,以及所有最短路中可能偏离数的最大值。

输入描述

第一行输入两个正整数 nn 和 mm,表示房间个数和通道个数。

接下来 mm 行,每行包含两个正整数 u,vu,v,表示房间 uu 到房间 vv 存在一条通道。

输出描述

输出最短飞行弹道条数和最大的可能偏离数,由于最短飞行弹道的条数可能很大,请对 998244353998244353 取模。

输入样例1

6 7

1 2

3 4

2 4

1 3

3 5

4 6

5 6

输出样例1

3 2

输入样例2

7 8

1 2

1 3

3 4

2 4

4 5

4 6

5 7

6 7

输出样例2

4 2

数据范围

对于测试点 11∼55:1≤n≤101≤n≤10。

对于测试点 66∼1010:1≤n≤501≤n≤50。

对于测试点 1111∼1515:1≤n≤10001≤n≤1000。

对于测试点 1616∼2020:1≤n≤1000001≤n≤100000。

对于 100%100% 的数据:n−1≤m≤2×nn−1≤m≤2×n,保证图连通。

测试样例下载

测试样例icon-default.png?t=O83Ahttps://kdyfiles.oss-cn-hangzhou.aliyuncs.com/kdy3b5c2d9b45b54ad48621c928788493ce.zip

解释

最短路计数问题。
第一次广搜
进行宽搜,记录出来 树组, 表示点 到 的最短路长度
第二次广搜
从 为起点,宽搜每个点,可以求出 到每个点的最短路,同时记 表示i的父亲(宽搜时的前继点)。


假设 n点为6点,那么4的父亲就是6 ,5的父亲也是6 。
需要考虑:如何判断一个点到另一个点是否在最短路径上。例如:从3到4的边和从3到5的边是在最短路上的边,而从3到1并不是。
得出结论:从x到y的边在最短路可以看作从x的最短距离等于y的最短距离+1 。

最终要求从1到n的最短路计数,可以离n从近到远的考虑,枚举(x,y) ,如果
,说明(x,y)在最短路边上,情况进行累加,

代码 

#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>	
#include<map>
#include<utility>
#include<cstdlib>
#define ll long long
#define pii pair<long long,long long>
#define endl "\n" 
using namespace std;
const int N=1e5+5,mod=998244353;
struct node{
	int to,nxt;
}edge[N<<2];
int n,m,cnt=1,head[N],hd=1,tail,q[N],dis[N],pre[N],tot[N],ans[N];
void add(int u,int v){
	edge[cnt].to=v;
	edge[cnt].nxt=head[u];
	head[u]=cnt++;
} 
void bfs(){
	memset(dis,-1,sizeof(dis));
	dis[n]=0;
	q[++tail]=n;
	while(hd<=tail){
		int u=q[hd++];
		for(int i=head[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			if(dis[v]==-1){
				dis[v]=dis[u]+1;
				pre[v]=u;
				q[++tail]=v;
			}
		}
	}
}
int main(){
	//freopen("missiles.in","r",stdin);
	//freopen("missiles.out","w",stdout);
	cin>>n>>m;
	while(m--){
		int u,v;
		cin>>u>>v;
		add(u,v),add(v,u);
	}
	bfs();
	tot[n]=1;
	for(int i=1;i<=tail;i++){
		int u=q[i],flag=0;
		for(int j=head[u];j;j=edge[j].nxt){
			int v=edge[j].to;
			if(dis[u]==dis[v]+1){
				ans[u]=max(ans[u],ans[v]);
				(tot[u]+=tot[v])%=mod;
				if(v!=pre[u]) flag=1;
			}
		}
		ans[u]+=flag;
	}
	cout<<tot[1]<<" "<<ans[1]<<endl;
    return 0;
}

SEE YOU AGAIN

THE END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值