10.15 2025多校CSP模拟赛5

如此如此,如何如何

T1 小 Z 爱计数(count)

黔岛题

初始值为 \(0\),有三种操作:$ +1,-1,reset $
给定 \(n\) 个二元组 \((a_i,b_i)\) 表示操作 $ a_i $ 次后值为 \(b_i\)
判断是否有一种操作序列满足所有二元组限制

按 $ a_i $ 排序后判一下奇偶性即可

code
#include<bits/stdc++.h>
using namespace std;
const int inf=1e6+10;
int t,n,c;
pair<int,int> e[inf];
inline void sol(){
	cin>>c>>n;
	for(int i=1;i<=n;i++) cin>>e[i].first>>e[i].second;
	sort(e+1,e+1+n);
	for(int i=1,da,db;i<=n;i++){
		// cout<<i<<'\n';
		da=e[i].first-e[i-1].first,db=e[i].second-e[i-1].second;
		if(abs(e[i].second)<da) continue;
		if(db==0){
			if(da%2==1){
				cout<<"No\n";
				return ;
			}
			continue;
		}
		if(da<abs(db)){
			cout<<"No\n";
			return ;
		}
		if((da-abs(db))%2==1){
			cout<<"No\n";
			return ;
		}
	}
	cout<<"Yes\n";
}
signed main(){
#ifndef LOCAL
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
#else
	freopen("count2.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>t;
	while(t--) sol();
}
/*

*/

T2 小 Z 爱划分(partition)

有趣$ DP $

定义区间 $ [l,r] $ 权值为 \((a_l \oplus a_{l+1} \dots a_r)\)
定义序列 $ a $ 的一组划分 $ [l_1,r_1],[l_2,r_2],\dots,[l_k,r_k] $ 的权值为所有 $ [l_i,r_i] $ 的权值之积
求序列 $ a $ 所有划分的权值平方和
对 $ 10^9+7 $ 取模
$ \sum n \leq 2 \times 10^5 $

赛时想到了神秘 $ O(n^3) $ 式子

\[f_{i,k}=\sum_{j=0}^{i-1} f_{j,k-1} \times xorsum(j+1,i)^2 \]

表示前 $ i $ 个元素,划分为 $ k $ 个区间的贡献
结果是去掉第二维也是对的……

正解
因为有异或,考虑拆位

在没有什么优化思路的时候,可以试着先思考一个弱化的问题

简化问题

考虑去掉平方

\[f_i=\sum_{j=0}^{i-1} f_j \times (s_i \oplus s_j) \]

$ s_i $ 为异或前缀和
考虑拆位

\[f_i=\sum_t^{len} \sum_{j=0}^{i-1} f_j \times 2^t \times [s_i(t)_2 \neq s_j(t)_2] \]

$ len $ 表示二进制表示下最大位数
$ o(t)2 $ 表示 $ o $ 在二进制表示下的第 $ t $ 位
记 $ w
$ 表示满足 $ s_k(t)_2=c $ 的所有 $ f_k $ 之和

光翼平方展开

\[(c_1+c_2+\dots+c_n)^2=\sum_{i=1}^n \sum_{j=1}^n c_ic_j \]

同理,$ DP $式子就变为

\[f_i=\sum_p^{len} \sum_q^{len} \sum_{j=0}^{i-1} f[j] \times 2^{p+q} \times [s_i(p)_2 \neq s_j(p)_2 \land s_i(q)_2 \neq s_j(q)_2] \]

设 $ w_{p,q,x,y} $ 表示满足 $ s_k(p)_2=x \land s_k(q)_2=y $ 的 $ f_k $ 的和
时间复杂度 $ O(\sum n \log^2 a_i) $

code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int inf=2e5+10;
const int mod=1e9+7;
int t,n;
int a[inf];
int e[60];
int s[inf],f[inf],w[30][30][2][2];
inline void sol(){
	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(w,0,sizeof w);
	memset(f,0,sizeof f);
	f[0]=1;
	for(int i=0;i<=n;i++){
		for(int p=0;p<30;p++)
			for(int q=0;q<30;q++)
				(f[i]+=e[p+q]*w[p][q][!((s[i]>>p)&1)][!((s[i]>>q)&1)]%mod)%=mod;
		for(int p=0;p<30;p++)
			for(int q=0;q<30;q++)
				(w[p][q][(s[i]>>p)&1][(s[i]>>q)&1]+=f[i])%=mod;
		// cout<<f[0]<<'\n';
	}
	cout<<f[n]<<'\n';
}
signed main(){
#ifndef LOCAL
	freopen("partition.in","r",stdin);
	freopen("partition.out","w",stdout);
#else
	freopen("a.in","r",stdin);
	// freopen("a.out","w",stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0);
	e[0]=1;
	for(int i=1;i<60;i++) e[i]=e[i-1]*2%mod;
	cin>>t;
	while(t--) sol();
}
/*

*/

T3 小 Z 爱优化(opti)

有 $ n $ 个元素,第 $ i $ 个对应权值 $ a_i $
相邻元素自由分组,每组元素个数为 $ 1 $ 或 $ 2 \(\ 定义一组的权值为组内元素的权值之和,求极差的最小值\ \) n \leq 2 \times 10^5 $

转化问题:
我们将所有 $ a_i $ 以及 $ a_i+a_{i+1} $ 看成位置不能移动的长为 $ 1 $ 和 $ 2 $ 的骨牌状物。
设 $ dp_{now,i,j} $ 表示在位置 $ now $,左右有无出格的最大值的最小
我们把序列搬到线段树上,就有
形如 $ (a_i) $ 的组初始化时使 $ f_{id(i),0,0}=a_i $
形如 $ (a_i,a_{i+1}) $ 的组初始化时使 $ f_{id(i),0,1}=f_{id(i+1),1,0}=a_i+a_{i+1} $
合并时

\[f_{now,i,j}=\min_{k=0,1} \{ \max \{ f_{lson,i,k}+f_{rson,k,j} \} \} \]

code
#include<bits/stdc++.h>
#define int long long
#define lson (id<<1)
#define rson (id<<1|1)
const int inf=4e5+5;
const int maxn=1e18;
using namespace std;
int T,n;
int tot,ans;
int a[inf];
int f[inf<<2][2][2];
struct jtr{
	int i,len,val;
}nod[inf];
inline void pushup(int id){
	for(int i=0;i<=1;i++){
		for(int j=0;j<=1;j++){
			f[id][i][j]=maxn;
			for(int k=0;k<=1;k++){
				f[id][i][j]=min(f[id][i][j],max(f[lson][i][k],f[rson][k][j]));
			}
		}
	}
}
inline void build(int id,int l,int r){
	if(l==r){
		f[id][0][0]=a[l];
		f[id][0][1]=a[l]+a[l+1];
		f[id][1][0]=-maxn;
		f[id][1][1]=maxn;
		return;
	}
	int mid=(l+r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
	pushup(id);
}
inline void update(int id,int l,int r,int pos,int len){
	if(l==r){
		f[id][0][len==2]=maxn;
		return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid) update(lson,l,mid,pos,len);
	else update(rson,mid+1,r,pos,len);
	pushup(id);
}
inline void solve(){
	ans=maxn;
	tot=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		nod[++tot]={i,1,a[i]};
	}
	for(int i=1;i<n;i++) nod[++tot]={i,2,a[i]+a[i+1]};
	sort(nod+1,nod+tot+1,[](jtr x,jtr y){return x.val<y.val;});
	build(1,1,n);
	for(int i=1;i<=tot;i++){
		if(f[1][0][0]>=maxn) break;
		ans=min(ans,f[1][0][0]-nod[i].val);
		update(1,1,n,nod[i].i,nod[i].len);
	}
	cout<<ans<<'\n';
}
signed main(){
#ifndef LOCAL
	freopen("opti.in","r",stdin);
	freopen("opti.out","w",stdout);
#else
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
#endif   
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>T;
	while(T--) solve();
}

T4 小 Z 爱考试(exam)

咕咕

posted @ 2025-10-15 21:44  Gon-Tata  阅读(40)  评论(0)    收藏  举报