【比赛记录】2025CSP-S模拟赛3

A. 光

首先有一个贪心,每次选择需要电量最大的位置加上 \(4\),给相邻的两个位置加上 \(2\),再给对角位置加上 \(1\)

这样不正确的原因是最后一些位置可能剩不下 \(4\) 个电量了,而我们四个四个放,就会产生浪费。那么我们之间暴力枚举最后每个位置都剩下多少(\(0\)\(3\)),然后再贪心即可。时间复杂度 \(O(256(a+b+c+d))\)

Code
#include<bits/stdc++.h>
#define ll long long
#define il inline
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int inf=0x3f3f3f3f;
int A,B,C,D;
il int solve(int a,int b,int c,int d){
	int res=0;
	while(a>0||b>0||c>0||d>0){
		res++;
		int tmp=max({a,b,c,d});
		if(a==tmp){
			a-=4,b-=2,c-=2,d--;
		}
		else if(b==tmp){
			b-=4,a-=2,d-=2,c--;
		}
		else if(c==tmp){
			c-=4,a-=2,d-=2,b--;
		}
		else{
			d-=4,b-=2,c-=2,a--;
		}
	}
	return res<<2;
}
namespace cplx{
	bool end;
	il double usdmem(){return (&begin-&end)/1048576.0;}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>A>>B>>C>>D;
	int ans=inf;
	for(int a=0;a<=3;a++){
		for(int b=0;b<=3;b++){
			for(int c=0;c<=3;c++){
				for(int d=0;d<=3;d++){
					ans=min(ans,a+b+c+d+solve(A-a-b/2-c/2-d/4,B-b-a/2-d/2-c/4,C-c-a/2-d/2-b/4,D-d-b/2-c/2-a/4));
				}
			}
		}
	}
	cout<<ans;
	return 0;
}
}
int main(){return asbt::main();}

B. 爬

对于每个点,我们考虑按位拆贡献。对于当前位,枚举有多少个为 \(1\) 的儿子节点爬上来,简单组合数计算方案数即可。注意当这个点上只有一个蚂蚁时不算贡献,还有要特判根。

Code
#include<bits/stdc++.h>
#define ll long long
#define il inline
#define pb push_back
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int maxn=1e5+5,mod=1e9+7;
int n,a[maxn],fa[maxn];
int _2[maxn],fac[maxn],inv[maxn];
vector<int> e[maxn];
il int qpow(int x,int y){
	int res=1;
	while(y){
		if(y&1){
			res=res*1ll*x%mod;
		}
		x=x*1ll*x%mod,y>>=1;
	}
	return res;
}
il int C(int x,int y){
	if(x<y||y<0){
		return 0;
	}
	return fac[x]*1ll*inv[y]%mod*inv[x-y]%mod;
}
namespace cplx{
	bool end;
	il double usdmem(){return (&begin-&end)/1048576.0;}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=2;i<=n;i++){
		cin>>fa[i];
		e[fa[i]].pb(i);
	}
	_2[0]=1;
	for(int i=1;i<=1e5;i++){
		_2[i]=_2[i-1]*2ll%mod;
	}
	fac[0]=1;
	for(int i=1;i<=n;i++){
		fac[i]=fac[i-1]*1ll*i%mod;
	}
	inv[n]=qpow(fac[n],mod-2);
	for(int i=n;i;i--){
		inv[i-1]=inv[i]*1ll*i%mod;
	}
	int ans=0;
	for(int i=1,tot;i<=n;i++){
		tot=e[i].size();
		for(int j=0,cnt;j<=30;j++){
			cnt=0;
			for(int u:e[i]){
				if(a[u]>>j&1){
					cnt++;
				}
			}
			for(int k=0;k<=cnt;k++){
				if(k==0){
					if(a[i]>>j&1){
						(ans+=(_2[tot-cnt]-1+mod)*1ll*_2[n-tot-(i==1?1:2)]%mod*_2[j]%mod)%=mod;
					}
				}
				else if(k==1){
					if(a[i]>>j&1){
						if(i!=1){
							(ans+=cnt*1ll*(_2[tot-cnt]-1+mod)%mod*_2[n-tot-2]%mod*_2[j]%mod)%=mod;
						}
					}
					else{
						(ans+=cnt*1ll*_2[tot-cnt]%mod*_2[n-tot-(i==1?1:2)]%mod*_2[j]%mod)%=mod;
						if(i!=1){
							(ans+=cnt*1ll*(_2[tot-cnt]-1+mod)%mod*_2[n-tot-2]%mod*_2[j]%mod)%=mod;
						}
					}
				}
				else if(k&1){
					if(a[i]>>j&1){
						if(i!=1){
							(ans+=C(cnt,k)*1ll*_2[tot-cnt]%mod*_2[n-tot-2]%mod*_2[j]%mod)%=mod;
						}
					}
					else{
						(ans+=C(cnt,k)*1ll*_2[tot-cnt]%mod*_2[n-tot-1]%mod*_2[j]%mod)%=mod;
					}
				}
				else{
					if(a[i]>>j&1){
						(ans+=C(cnt,k)*1ll*_2[tot-cnt]%mod*_2[n-tot-(i==1?1:2)]%mod*_2[j]%mod)%=mod;
					}
				}
			}
		}
	}
	cout<<ans;
	return 0;
}
}
int main(){return asbt::main();}
/*
5
64 19 1 46 1 
1 1 1 1 
*/

C. 字符串

考虑 \(c\) 的限制非常的讨厌,数据范围是允许我们去 \(O(n)\) 枚举的,所以我们首先就枚举 \(\underbrace{BBB\dots B}_{c}A\underbrace{BBB\dots B}_{c}\) 这样的有几段。然后我们把剩下的 \(A\)\(B\) 填充进去。

首先填 \(A\),显然可以在最开头填一个,产生 \(1\) 的贡献。然后本质上就是每填进去长为 \(a\)\(A\) 序列,就产生 \(1\) 的贡献。

然后填 \(B\),如果当前最后一个字母是 \(A\),那显然可以在最后面添加一个 \(B\) 来产生 \(1\) 的贡献。然后我们把所有长为 \(c\)\(B\) 串都填成 \(k\cdot b+1,k\in\mathbb{Z}\) 的长度。此时再多一段长为 \(b\)\(B\) 串就会再产生 \(1\) 的贡献。不要忘了如果 \(c>b\) 那么一开始就会有贡献。

Code
#include<bits/stdc++.h>
#define ll long long
#define il inline
using namespace std;
namespace  asbt{
namespace cplx{bool begin;}
int T,n,m,a,b,c;
il void solve(){
	cin>>n>>m>>a>>b>>c;
	int ans=0;
	for(int i=0;;i++){ // BBB/A 有几段 
		int cnta=i/2,cntb=(i+1)/2;
		int A=n-cnta,B=m-cntb*c;
		if(A<0||B<0){
			break;
		}
		int res=i;
		res+=(c-(c-1)%b-1)/b*cntb;
		if(A>0){
			A--,res++;
		}
		res+=A/a;
		if(i%2==0&&B>0){
			B--,res++;
		}
		int tmp=((1-c)%b+b)%b;
		if(tmp){
			int num=min(B/tmp,cntb);
			res+=num,B-=num*tmp;
		}
		res+=B/b;
		ans=max(ans,res);
	}
	cout<<ans<<"\n";
}
namespace cplx{
	bool end;
	il double usdmem(){return (&begin-&end)/1048576.0;}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}
}
int main(){return asbt::main();}

D. 奇怪的函数

首先,这个函数其实显然是一个分三段的连续的函数,形如:

\[F(x)=\begin{cases} L&\ x\le l\\ x+D&\ l<x<r\\ R&\ x\ge r \end{cases} \]

于是我们维护函数的 \(L\)\(R\)\(D\),即可通过没有修改的那个包。维护这三个值是可以线性完成的。

考虑一次修改后我们就要再整个扫一遍,无法接受。考虑分块,那么每次修改重构一个块,查询就去扫所有块,单次时间都是 \(O(\sqrt{n})\) 的。

Code
#include<bits/stdc++.h>
#define int long long
#define il inline
using namespace std;
namespace  asbt{
namespace cplx{bool begin;}
const int maxn=1e5+5,maxb=320,inf=1e18;
int n,m,blen,bnum,bel[maxn],st[maxb],ed[maxb];
struct{
	int opt,val;
}a[maxn];
struct{
	int L,R,D;
}b[maxb];
il void upd(int x){
	b[x].L=-inf,b[x].R=inf,b[x].D=0;
	for(int i=st[x];i<=ed[x];i++){
		switch(a[i].opt){
			case 1:{
				b[x].L+=a[i].val;
				b[x].R+=a[i].val;
				b[x].D+=a[i].val;
				break;
			}
			case 2:{
				b[x].L=min(b[x].L,a[i].val);
				b[x].R=min(b[x].R,a[i].val);
				break;
			}
			default:{
				b[x].L=max(b[x].L,a[i].val);
				b[x].R=max(b[x].R,a[i].val);
				break;
			}
		}
	}
}
namespace cplx{
	bool end;
	il double usdmem(){return (&begin-&end)/1048576.0;}
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].opt>>a[i].val;
	}
	blen=sqrt(n);
	bnum=(n+blen-1)/blen;
	for(int i=1;i<=bnum;i++){
		st[i]=ed[i-1]+1;
		ed[i]=min(ed[i-1]+blen,n);
		for(int j=st[i];j<=ed[i];j++){
			bel[j]=i;
		}
		upd(i);
	}
	cin>>m;
	while(m--){
		int opt,x,val;
		cin>>opt>>x;
		if(opt==4){
			for(int i=1;i<=bnum;i++){
				x+=b[i].D;
				x=min(x,b[i].R);
				x=max(x,b[i].L);
			}
			cout<<x<<"\n";
		}
		else{
			cin>>val;
			a[x].opt=opt,a[x].val=val;
			upd(bel[x]);
		}
	}
	return 0;
}
}
signed main(){return asbt::main();}
posted @ 2025-03-22 14:07  zhangxy__hp  阅读(55)  评论(3)    收藏  举报