蓝桥 月赛26 20250405

蓝桥 月赛26 20250403

https://www.lanqiao.cn/oj-contest/senior-26/

A:

题目大意:求 \(\lceil 2025/15\rceil\)

void solve(){
	cout<<135;
}

签到

B:
题目大意:

void solve(){
	int n,m;
	cin>>n>>m;
	vector<int> l(n+1),r(n+1);
	for (int i=1;i<=n;i++) cin>>l[i]>>r[i];
	int p=1;
	LL ans=0;
	for (int i=1;i<=n;i++){
		if (p>=l[i]&&p<=r[i]) continue;
		if (abs(l[i]-p)<abs(r[i]-p)){
			ans+=abs(l[i]-p);
			p=l[i];
		}else{
			ans+=abs(r[i]-p);
			p=r[i];
		}
	}
	cout<<ans;
}

蓝桥特有的神奇题目

因为必须按顺序询问每个区间 \([l,r]\) ,所以枚举记录当前的位置 \(p\)

如果 \(p\) 在下一个区间内,那么不需要移动,如果不在,选择移动到最近的区间端点

C:

题目大意:

void solve(){
	int n,k;
	cin>>n>>k;
	vector<int> a(n+1);
	for (int i=1;i<=n;i++) cin>>a[i];
	sort(a.begin()+1,a.end());
	a[1]+=a[2];
	a[2]=0;
	sort(a.begin()+1,a.end());
	LL ans=0;
	for (int i=1;i<=n/2;i++) ans+=a[i];
	cout<<ans;
}

可以证明,倒汤圆的操作一定不会使答案变优

假设两碗汤圆为 \(a,b\)

  • \(a,b\) 都是在少的 \(\lfloor n/2 \rfloor\) 碗中
    • 如果 \(a+b\) 也在少的 \(\lfloor n/2 \rfloor\) 碗中,那么可以得到的总数不变
    • 如果 \(a+b\) 不在少的 \(\lfloor n/2 \rfloor\) 碗中,那么可以得到的总数会变为 \(0+k\) 其中 \(k,k<a+b\) 是之前的第 \(\lfloor n/2 \rfloor+1\)
  • \(a,b\) 其中一碗在少的 \(\lfloor n/2 \rfloor\) 碗中
    • 一碗会变为 \(0\) ,一碗变得更多,那么总数会变少
  • \(a,b\) 都不在少的 \(\lfloor n/2 \rfloor\) 碗中
    • 一碗会变为 \(0\)那么可以得到的总数会减少第 \(\lfloor n/2 \rfloor\) 碗的数量

这里有个题意问题,操作是否必须要做

如果可以不做,那么直接排序输出即可,如果必须要做,那么考虑将操作带来的负收益最小化

第一轮将最小的两碗相互倒,a[1]+=a[2];a[2]=0;

第二轮利用 a[2]=0 ,将 a[3] 中的汤圆移动到 a[2]

往后同理,都利用空碗往后倒腾,所以最后的总数为 a[1]+=a[2];a[2]=0; 操作后重新排序的前 n/2 个总和

D:

题目大意:

const int mod=1e9+7;

LL dp[1000010];

void solve(){
	dp[1]=1,dp[2]=2;
	for (int i=3;i<=1000000;i++)
		dp[i]=(dp[i-2]*(i-1)%mod+dp[i-1])%mod;
	int t;
	cin>>t;
	while (t--){
		int n;
		cin>>n;
		cout<<dp[n]<<endl;
	}
}

定义 \(dp_i\) 表示防止 \(i\) 个物品的方案数,观察知道 \(dp_1=1,dp_2=2\)

考虑第 \(3\) 个物品的方案数,如因为要保证对称性,所以第 \(3\) 个物品一定可以放在 \((3,3)\) 的位置上,那么这样的方案数为 \(dp_2\)

如果第 \(3\) 个物品放在 \((3,2)\) ,则前 \(2\) 个物品其中一个不能放在 \((1,2),(2,2)\) 上,只能放在 \((2,3)\) 上,则这样的方案数为 \(dp_1\)

同理有放在 \((3,1)\) 的方案数,手玩几次可以得到状态转移方程

\[dp_i=(n-1)*dp_{i-2}+dp_{i-1} \]

其中 \((n-1)*dp_{i-2}\) 代表了第 \(i\) 个物品放在 \(\sum_{j=1}^{i-1}(i,j)\) 的方案数求和,\(dp_{i-1}\) 表示放在 \((i,i)\) 的方案数

E:

题目大意:

void solve(){
	int n;
	cin>>n;
	vector<int> a(n+1);
	for (int i=1;i<=n;i++) cin>>a[i];
	sort(a.begin()+1,a.end());
	for (int i=1;i<=n;i++){
		int p=1,ans=0;
		while (p<=n){
			ans++;
			p=lower_bound(a.begin()+1,a.end(),a[p]+i)-a.begin();
		}
		cout<<ans<<' ';
	}
}

首先肯定是读入数据后排序

对每个 \(k\) 都需要扫描一次 \(a\) ,对排序后的 \(a\) 可以做 lower_bound 操作

考虑 \(p\) 记录当前访问到的 \(a_i\) 的位置,每次向后二分找第一个大于等于 \(a_p+k\) 的元素,那么将 \(p\) 移动到找到的元素上

然后计数加一,表示当前可以邀请的朋友数多一

我们的 \(p\)\(1\) 开始,这是最优的,如果从 \(2\) 开始,那么存在 \(a_i\) 导致 \(a_i-a_2<k,a_i-a_1>k\) 这样答案可能会劣

可能会这样想,当 \(p\) 走到了 \(a_i\) 上,如果有 \(a_j-a_2>k,a_j-a_i<k\) 这样不是也会使答案变劣吗?

但其实并不会,因为如果 \(a_j-a_2>k\) 那么一定存在 \(a_j-a_1>1\)相当于 \(p\) 不走到 \(a_i\) 上,答案都是一样的

如果走到了 \(a_i\) 上,就有可能存在 \(a_j-a_i>k\) ,会使得答案变优 ,存在变优的可能且一定不会劣,那么就是优的

F:

题目大意:

void solve(){
	int n;
	cin>>n;
	vector<int> a(n+1),b(n+1);
	for (int i=1;i<=n;i++) cin>>a[i];
	for (int i=1;i<=n;i++) cin>>b[i];
	LL sum=0,k=1;
	for (int i=2;i<=n;i++){
		if (a[i]+min(b[i],b[i-1])>a[i-1]+max(b[i],b[i-1]))
			k++;
		else
			sum+=k*(k-1)/2,k=1;
	}
	if (k!=1) sum+=k*(k-1)/2;
	cout<<sum;
}

首先考虑简单情况,\(r-1=l\) ,即区间只有两个元素

如果当前区间为必胜区间,那么满足

\[a_{i-1}+{\rm{max}}(b_{i-1},b_i)<a_i+{\rm{min}}(b_{i-1},b_i)\\ \implies b_i-b_{i-1}\le{\rm{max}}(b_{i-1},b_i)-{\rm{min}}(b_{i-1},b_i)<a_i-a_{i-1} \]

然后区间扩张,如果也为必胜区间,那么满足

\[a_i+{\rm{max}}(b_{i},b_{i+1})<a_{i+1}+{\rm{min}}(b_{i},b_{i+1})\\ \implies b_{i+1}-b_{i}\le{\rm{max}}(b_{i},b_{i+1})-{\rm{min}}(b_{i},b_{i+1})<a_{i+1}-a_{i} \]

两式相加得

\[b_{i+1}-b_{i-1}< a_{i+1}-a_{i-1} \]

考虑区间 \([i-1,i+1]\) ,如果满足

\[a_{i-1}+{\rm{max}}(b_{i-1},b_{i+1})<a_{i+1}+{\rm{min}}(b_{i-1},b_{i+1})\\ \implies b_{i+1}-b_{i-1}\le{\rm{max}}(b_{i-1},b_{i+1})-{\rm{min}}(b_{i-1},b_{i+1})<a_{i+1}-a_{i-1} \]

又因为对于 \(b_i,b_j\)\({\rm{max}}(b_{i},b_{j})-{\rm{min}}(b_i,b_j)>0>{\rm{min}}(b_i,b_j)-{\rm{max}}(b_i,b_j)\)

所以综上可以得出结论,如果区间 \([l,r]\) 是必胜区间,那么他的所有子区间也都为必胜区间

对于每段最大的必胜区间,组合数两个端点有 \(C_{r-l+1}^2=k*(k-1)/2\),累加答案

posted @ 2025-04-13 14:27  才瓯  阅读(13)  评论(0)    收藏  举报