2025模拟赛Round9

T1 T2 T3 T4 T5 T6
\({\color{#F39C11} 普及− }\) \({\color{#FFC116} 普及/提高− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\)

参赛网址:https://boyacoding.cn/contest

特别感谢 @Sunpicnic对本文格式进行的修正

T3,T5搭建未完成

T1 一道复杂的构造题【2025暑假集训T1】

T1 题面传送门

题目难度:\({\color{#F39C11} 普及− }\)

算法标签:其他,位运算,贪心,数论,构造

思路

由于大样例具有提示性,无下发文件。

在看过数据范围,(主要是 \(m\) 为偶数和 \(m \le n\) ),我发现:因为 \(\gcd(a_1,a_2,...,1)=1\) 所以 对于每个合法的 \(m\) 都有 $$m\equiv1\pmod{2}$$,当 \(m\) 是偶数时:输出 \(-1\)

然后 又因为 \(\gcd(x)=x\) 以及 按位与 运算的性质,我想到了通过二进制组合出 \(m\) ,因为 \(m \le 10^5\),所以在二进制下 \(m\) 的位数 小于 20。

总结

首先找出 \(m\) 在二进制下为 \(1\) 的位置( \(1\) 除外),将他们每个都化为独立一组,然后将剩下的数和 \(1\) 化为一组。

AC代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int maxn=1e5+5;
int n,m;
int a[maxn];
map<int,int> M;

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>m;
	if (m%2==0){
		cout<<-1;
		return 0;
	}
	int cnt=0;
	for (int i=2;i<=m;i<<=1){
		if (m&i){
			a[++cnt]=i,M[i]++;
			if (i>n){
				cout<<-1;
				return 0;
			}
		}
	}
	for (int i=1;i<=cnt;i++)	cout<<a[i]<<" ";
	for (int i=1;i<=n;i++){
		if (M[i])	continue;
		cout<<i<<" ";
	}
	cout<<"\n";
	cout<<cnt+1<<"\n";
	for (int i=1;i<=cnt;i++)	cout<<i<<" "<<i<<"\n";
	cout<<cnt+1<<" "<<n<<"\n";
	return 0;
}

T2 茳侨串【2025暑假集训T2】

T2 题面传送门

题目难度:\({\color{#FFC116} 普及/提高− }\)

算法标签:动态规划,搜索,枚举

思路

首先我们发现茳侨串在将所有相同 \(1\)\(0\) 缩在一起后,只有 \(0101\)\(1010\) 两种状态。

因为两种状态一样,我们考虑 \(0101\) 一种:

它分为 \(4\) 各部分 \(0\) , \(1\) , \(0\)\(1\) ,因为实在没想到其他算法QAQ,我们构造 \(DP\) : \(f_{i,j},j\in[1,4]\) 表示在 \(i\) 的位置 \(j\) 的部分的最小翻转数。

\(f_{i,j}=min{f_{i-1,j},f_{i-1,j-1}}\)

总结

\(f_{i,j}=min{f_{i-1,j},f_{i-1,j-1}}\)

AC代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int maxn=2e5+5;
int n;
int cnt,ans;
int a[maxn],siz[maxn];
int dp[maxn][5];
string s;

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>s;
	for (int i=0;i<n-1;i++){
		if (s[i]!=s[i+1])	cnt++;
	}
	if (cnt==0)	cout<<2;
	else if (cnt==1)	cout<<1;
	else if (cnt==2){
		if (n==4)	cout<<2;
		else	cout<<1;
	}
	else if (cnt==3)	cout<<0;
	else {
		int num=0;
		for (int i=0;i<n;i++){
			int j=i;
			while (j<n&&s[j+1]==s[i])	j++;
			if (j==n){
				j--;
				siz[++num]=j-i+1;
				a[num]=s[i]-'0';
				break;
			}
			siz[++num]=j-i+1;
			a[num]=s[i]-'0';
			i=j;
		}
		for (int i=0;i<=num;i++){
			for (int j=1;j<=4;j++){
				dp[i][j]=1e9;
			}
		}
		dp[0][1]=0;
		for (int i=1;i<=num;i++){
			for (int j=1;j<=min(i,4ll);j++){
				if (j==1)	dp[i][j]=dp[i-1][j]+(j%2==a[i])*siz[i];
				else dp[i][j]=min(dp[i-1][j],dp[i-1][j-1])+(j%2==a[i])*siz[i];
			}
		}
		ans=dp[num][4];
		
		for (int i=0;i<=num;i++){
			for (int j=1;j<=4;j++){
				dp[i][j]=1e9;
			}
		}
		dp[0][1]=0;
		for (int i=1;i<=num;i++){
			for (int j=1;j<=min(i,4ll);j++){
				if (j==1)	dp[i][j]=dp[i-1][j]+(j%2!=a[i])*siz[i];
				else dp[i][j]=min(dp[i-1][j],dp[i-1][j-1])+(j%2!=a[i])*siz[i];
			}
		}
		ans=min(ans,dp[num][4]);
		cout<<ans;
	}
	return 0;
}

T3 好路径数【2025暑假集训T3】

T3 题面传送门

题目难度:\({\color{#3498DB} 提高+/省选− }\)

算法标签:其他,双指针扫描,数据结构,并查集

tip:还没改出来

思路

总结

AC代码

T4 江桥游览花园【2025暑假集训T4】

T4 题面传送门

题目难度:\({\color{#3498DB} 提高+/省选− }\)

算法标签:动态规划

tip:赛时不会

感谢赛后 @hanbingqigu 讲解

思路

总结

我们可以发现 对于每个位置,只会去到的两个地点,于是我们可以构造 \(DP\) 方程

\(f_{i,j,0}\) 表示第一种花取到 \(i\) ,第二种花去到 \(j\) ,现在在第一种花的最短距离

\(f_{i,j,1}\) 表示第一种花取到 \(i\) ,第二种花去到 \(j\) ,现在在第二种花的最短距离

\(f_{i+1,j,0}=min(f_{i+1,j,0},f_{i,j,0}+dis(i,i+1));\)

\(f_{i,j+1,1}=min(f_{i,j+1,1},f_{i,j,0}+dis(i,j+n+1));\)

\(f_{i+1,j,0}=min(f_{i+1,j,0},f_{i,j,1}+dis(j+n,i+1));\)

\(f_{i,j+1,1}=min(f_{i,j+1,1},f_{i,j,1}+dis(j+n,j+n+1));\)

AC代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int maxn=2e3+5;
int n,m;
int x[maxn],y[maxn];
int f[maxn][maxn][2];

int dis(int i,int j){
	int res=abs(x[i]-x[j])*abs(x[i]-x[j])+abs(y[i]-y[j])*abs(y[i]-y[j]);
	return res;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>m;
	for (int i=1;i<=n+m;i++)	cin>>x[i]>>y[i];
	memset(f,0x3f,sizeof(f));
	f[1][0][0]=0;
	for (int i=1;i<=n;i++){
		for (int j=0;j<=m;j++){
			f[i+1][j][0]=min(f[i+1][j][0],f[i][j][0]+dis(i,i+1));
			f[i][j+1][1]=min(f[i][j+1][1],f[i][j][0]+dis(i,j+n+1));
			f[i+1][j][0]=min(f[i+1][j][0],f[i][j][1]+dis(j+n,i+1));
			f[i][j+1][1]=min(f[i][j+1][1],f[i][j][1]+dis(j+n,j+n+1));
		}
	}
	cout<<f[n][m][0];
	return 0;
}

T5 环计数【2025暑假集训T5】

T5 题面传送门

题目难度:\({\color{#3498DB} 提高+/省选− }\)

算法标签:动态规划,状压DP

tip:还没改出来

思路

总结

AC代码

T6 数学竞赛2【2025暑假集训T6】

T6 题面传送门

题目难度:\({\color{#3498DB} 提高+/省选− }\)

算法标签:其他,数据结构,线段树,二分查找

tip:赛时不会

思路

总结

同线段树

P4145 上帝造题的七分钟 2 / 花神游历各国

唯一复杂的\(f(v)\)

\(f(x)=floor(y)\)

\(\frac{y*(y+1)}{2}=x\)

已知 \(x\) ,求 \(y\)

根据 一元二次方程 求根公式

众所周知,对一元二次方程 \(ax ^ 2 + bx + c = 0(a \neq 0)\),可以用以下方式求实数解:

  • 计算 \(\Delta = b ^ 2 - 4ac\),则:
    1. 若 \(\Delta < 0\),则该一元二次方程无实数解。
    2. 否则 \(\Delta \geq 0\),此时该一元二次方程有两个实数解 \(x _ {1, 2} = \frac{-b \pm \sqrt \Delta}{2a}\)

例如:

  • \(x ^ 2 + x + 1 = 0\) 无实数解,因为 \(\Delta = 1 ^ 2 - 4 \times 1 \times 1 = -3 < 0\)
  • \(x ^ 2 - 2x + 1 = 0\) 有两相等实数解 \(x _ {1, 2} = 1\)
  • \(x ^ 2 - 3x + 2 = 0\) 有两互异实数解 \(x _ 1 = 1, x _ 2 = 2\)

--来自 P9750 [CSP-J 2023] 一元二次方程

一元二次方程 \(y^2+y-2x=0\)

判别式 \(\Delta=\sqrt{8x^2+1}>0\)

\(y=\frac{\sqrt{8x^2+1}-1}{2}\)

AC代码

#include <bits/stdc++.h>
#define int long long
#define mid ((l+r)>>1)
#define ls (mid*2)
#define rs (mid*2+1)
using namespace std;

const int maxn=2e5+5;
const int mod=998244353;
int n,m;
int a[maxn];
int t[maxn<<2],flag[maxn<<2];

void build(int id,int l,int r){
    if (l==r){
        t[id]=a[l];
        if (t[id]<=1)   flag[id]=1;
        return ;
    }
    build(ls,l,mid);
    build(rs,mid+1,r);
    t[id]=(t[ls]+t[rs])%mod;
    flag[id]=flag[ls]&&flag[rs];
}

void update(int id,int l,int r,int x,int y){
    if (r<x||l>y)   return ;
    if (flag[id])   return ;
    if (l==r){
        t[id]=(sqrt(8*t[id]+1)-1)/2;
        t[id]%=mod;
        if (t[id]<=1)   flag[id]=1;
        return ;
    }
    update(ls,l,mid,x,y);
    update(rs,mid+1,r,x,y);
    t[id]=(t[ls]+t[rs])%mod;
    flag[id]=flag[ls]&&flag[rs];
}

int query(int id,int l,int r,int x,int y){
    if (r<x||l>y)   return 0;
    if (x<=l&&r<=y) return t[id]%mod;
    int res=0;
    res+=query(ls,l,mid,x,y);res%=mod;
    res+=query(rs,mid+1,r,x,y);res%=mod;
    return res;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    for (int i=1;i<=n;i++)  cin>>a[i];
    build(1,1,n);
    while (m--){
		int op,x,y;
        cin>>op>>x>>y;
        if (op==0)  update(1,1,n,x,y);
        else    cout<<query(1,1,n,x,y)<<"\n";
    }
    return 0;
}
posted @ 2025-09-14 08:19  Zzqyoung1121  阅读(9)  评论(0)    收藏  举报