首页 > 其他分享 >暑假集训CSP提高模拟6

暑假集训CSP提高模拟6

时间:2024-07-24 21:08:57浏览次数:14  
标签:const int cin 集训 maxn 暑假 ans tie CSP

image

赛时在 \(T2\) 浪费时间太多,导致 \(T4\) 暴力没时间想了,总是想把 \(T2\) 这种题当大型分讨来做

A. 花间叔祖

[ARC148A] mod M

观察性质可以发现,答案要么是1,要么是2,把是1的情况找出来剩下的就是2。

考虑什么时候是1,如果一个数列模上一个数结果相同,那么他们的差一定是这个模数的整数倍,直接求差的 \(gcd\) 即可

点击查看代码
#include<bits/stdc++.h>
const int maxn=2e5+10;
using namespace std;
int n,a[maxn],mod,flag;
int temp;
int main()
{ 
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	sort(a+1,a+n+1); 
	for(int i=2;i<=n;i++)
	{
		temp=__gcd(a[i]-a[i-1],temp);
		if(!mod)
		{
			if(temp==1)
			{
				flag=1;
				break;
			} 
			mod=temp;
		}
		else
		{
//			cout<<mod<<" "<<temp<<endl; 
			if(__gcd(mod,temp)==1)
			{
				flag=1;
				break;
			}
			else
			{
				mod=__gcd(mod,temp);
			}
		}
	}

	if(flag)
	{
		cout<<2;
	}
	else
	{
		cout<<1;
	}
	

	return 0;
}  
/*
10
3785 5176 10740 7744 3999 3143 9028 2822 4748 6888

*/

B. 合并r

[ARC107D] Number of Multisets

方案数很多,考虑\(DP\),这里我们把题目看为,先选 \(k\) 个1,再由这 \(k\) 个1分裂为 \(n\) 个数的方案数

设 $ f_i,_j $ 表示为当前由 \(i\) 个数组成的和为 \(j\) 的方案数,每个值可以直接分为原来的\(1/2\),所以是由 \(j*2\) 个转移的

而在 \(j-j*2\) 的值都可以由这 \(i\) 个数替换几个 \(j\) 成 \(j*2\)组成,这些方案是在 \(j*2\) 的方案中存在的(\(j*2\)也是由这些

值替换而来),所以 \(f_i,_j\) = $ f_{i-1,_j-1} $ + \(f_{i,_j * 2}\)

点击查看代码
#include<bits/stdc++.h>
#define de double 
const int mod=998244353; 
const int maxn=5e3+10;
using namespace std;
int n,k,f[maxn][maxn];

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>k;
	f[0][0]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=i;j>=1;j--)
		{
			f[i][j]=f[i-1][j-1];
			if(j*2<=i)f[i][j]+=f[i][j*2];
			f[i][j]%=mod;
		}
	}
	cout<<f[n][k];
		
	return 0;
}

C. 回收波特

[ARC149D] Simultaneous Sugoroku

思路很巧,注意到值域很小,所以对值域操作,每次以坐标分为两部分,让小的一部分向多的一部分连边,他们最后的位置是

相反的,每次舍掉小的一部分,最后没有指令了,但值域还有,那值域中的点即为不能到原点,细节看代码

点击查看代码
#include<bits/stdc++.h>
const int maxn=2e6+10;
using namespace std;
int m,n,x[maxn],to[maxn],ans[maxn],lst[maxn],d; 

void get(int x)
{
	if(ans[x]||lst[x])return ;
	get(to[x]);
	ans[x]=ans[to[x]],lst[x]=-lst[to[x]];
} 

int main()
{
//	freopen("bot_ex3.in","r",stdin);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>x[i];
	int p=0,l=1,r=1e6;
	for(int i=1;i<=m;i++)
	{
		cin>>d;
		if(p<l)p+=d;
		else if(p>r)p-=d;
		if(p<l||p>r)continue;
		ans[p]=i;
		if(p-l<r-p)
		{
			for(int j=l;j<p;j++)to[j]=2*p-j;
			l=p+1;
		}
		else
		{
			for(int j=r;j>p;j--)to[j]=2*p-j;
			r=p-1;
		} 
	}
	for(int i=l;i<=r;i++) lst[i]=i-p;
	for(int i=1;i<=n;i++)
	{
		get(x[i]);
		if(ans[x[i]])cout<<"Yes "<<ans[x[i]]<<'\n';
		else cout<<"No "<<lst[x[i]]<<'\n';
	}
	
	return 0;
}

最后处理不能到的坐标是 \(i-p\) ,首先这个区间到最后了(没有连边),那么每次 \(p\) 就是向区间方向移动(自己手模一下),

要么是一直不到 \(l\),最后一定大于0,直接减,要么就是由不到 \(l\) 到超过 \(r\) ,再一直向左,这样最后坐标是小于0的,还是

直接减就行。

D. 斗篷

P6949 [ICPC2018 WF] Triangles

对于每个点维护 \(L_{x, y}\) 表示这个点向左上延伸的最大距离,维护 \(R_{x, y}\) 表示这个点向右上延伸的最大距离;维护 \(len\) 表示这个

点向左延伸到的位置。枚举每个点 \((x, y)\) 作为三角形的右下角,枚举 \((x, t)\) 作为三角形的左下角,显然

\(t\in [\max(pre_{x, y}, y - L_{x, y}), y-1]\) ,如果 \(t\) 满足 \(R_{x, t}\ge y-t\) ,则对答案产生 \(1\) 的贡献。

考虑优化:简单移项有 \(R_{x,t}+t\ge y\) 。

令 \(L=\max(pre_{x, y}, y - L_{x, y}), R=y-1\) ,即统计 \([L, R]\) 区间内满足 \(R_{x,t}+t\ge y\) 的 \(t\) 的个数。

单点修改,区间查询,用树状数组维护

点击查看代码
#include<bits/stdc++.h>
const int maxn=6010;
using namespace std;
int r,c;
long long ans;
char s[maxn][maxn<<1];
int L[2][maxn<<1],R[2][maxn<<1];
int C[maxn<<1];
struct lsx
{
	inline int lowbit(int x){return x&-x;}
	
	inline void add(int x,int y)
	{
		while(x<=c)
		{
			C[x]+=y;
			x+=lowbit(x);
		}
	}
	
	inline int query(int x)
	{
		int temp=0;
		while(x)
		{
			temp+=C[x];
			x-=lowbit(x);
		}
		return temp;
	}
}e;

vector<int>q[maxn<<1];
void solve()
{
	int now=1,pre=0;
	memset(L,0,sizeof L),memset(R,0,sizeof R);
	for(int t=3;t<=r;t+=2,swap(now,pre))
	{
		memset(C,0,sizeof C),memset(L[now],0,sizeof L[now]),memset(R[now],0,sizeof R[now]);
		int len=0;
		for(int i=1;i<=c;i++)
			if(s[t][i]=='x')
			{
				if(i>2&&(s[t-1][i-1]==92||s[t-1][i-1]==47))L[now][i]=L[pre][i-2]+1;
				else L[now][i]=0; 
				if(i<c&&(s[t-1][i+1]==92||s[t-1][i+1]==47))R[now][i]=R[pre][i+2]+1;
				else R[now][i]=0; 
				
				if(s[t][i-1]=='-')len++;
				else len=0;
				int temp=min(len,L[now][i]);
				if(temp) ans+=e.query(i)-e.query(i-temp*4-1);
				
				for(int j=0;j<q[i].size();j++) e.add(q[i][j],-1);
				q[i].clear();
				if(R[now][i])
				{
					e.add(i,1);
					if(i+R[now][i]*4<=c)q[i+R[now][i]*4].push_back(i);
				} 
			}
	}
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>r>>c;
	r=r*2-1,c=c*2;
	string tmp;
	getline(cin,tmp);
	for(int i=1;i<=r;i++) 
	{
        getline(cin,tmp);
        for(int j=1;j<=c;j++)s[i][j]=tmp[j-1];
	} 
	solve();
	reverse(s+1,s+r+1);
	solve();
	cout<<ans;
	
	return 0;
}

标签:const,int,cin,集训,maxn,暑假,ans,tie,CSP
From: https://www.cnblogs.com/oceansofstars/p/18321718

相关文章

  • 暑假集训CSP提高模拟3
    暑假集训CSP提高模拟32/35反向挂了若干分又正向挂了若干T1abc猜想水,随便变形推个柿子糊个快速幂就好了T2简单的排列最优化题考虑只计算每次右移的\(delta\),我们发现一个点只会在到贡献为\(0\)的位置和序列开头会改变对\(delta\)的贡献,直接算就好,\(O(n)\)的T3简单......
  • [题解]P9755 [CSP-S 2023] 种树
    P9755[CSP-S2023]种树迟来的补题本题是让最小化所有树长到指定高度日期的最大值,于是想到二分答案。那么,对于一个给定的期限\(x\),如何判断是否能在这个日期内完成任务呢?首先我们发现前\(n\)天每天都要种树,那么假设我们已经知道了每个地块最晚哪个日期种树,能保证在期限\(x\)......
  • ssy学校暑假集训游记
    7.24日集训第二天不要问为什么第二天才写,这不重要。上午模拟赛,先开T1订正......T1先引入逆序对,如果有$1$在$0$前面,就算一组逆序对。对于这个题,很容易可以猜想出最后的结果$000....0011..11$。回看题目中所给的条件,无论是$10$,$100$,$110$还是$1010$,他翻转过去一定能减少......
  • 24暑假算法刷题 | Day20 | LeetCode 235. 二叉搜索树的最近公共祖先,701. 二叉搜索树中
    目录235.二叉搜索树的最近公共祖先题目描述题解701.二叉搜索树中的插入操作题目描述题解450.删除二叉搜索树中的节点题目描述题解235.二叉搜索树的最近公共祖先点此跳转题目链接题目描述给定一个二叉搜索树,找到该树中两个指定节点的最近公共祖先。百度......
  • 24暑假算法刷题 | Day21 | LeetCode 669. 修剪二叉搜索树,108. 将有序数组转换为二叉搜
    目录669.修剪二叉搜索树题目描述题解108.将有序数组转换为二叉搜索树题目描述题解538.把二叉搜索树转换为累加树题目描述题解669.修剪二叉搜索树点此跳转题目链接题目描述给你二叉搜索树的根节点root,同时给定最小边界low和最大边界high。通过修剪二叉......
  • 『模拟赛』暑假集训CSP提高模拟6
    RankA.花间叔祖签到题,但没切。一眼出思路找最大公因数,过了大样例发现同余的情况也合法,然后开始优化,成功从68pts到了88pts。考虑正解,首先答案不是一就是二。若答案是一,即所有数可在模某数\(x\)意义下同余。不妨将每个数化成\(a_i=k\timesx+d\)的形式,则若存在一个......
  • 2024暑假集训总结
    2024暑假集训总结知识点清单:树状数组拓展:(1)k维前缀和(2)树状数组+倍增没码过,小慌线段树:(1)线段树不仅仅是一个维护区间和、区间最值或者类似于方差那道题,维护区间的平方等等信息,它的深层是将区间拆分为\(O(logn)\)个子区间从而将修改与查询降为\(O(logn)\)级别,因此对于线......
  • 2024 暑假集训
    树状数组&线段树线段树合并,主席树等知识点是第一次接触。同时对扫描线能解决的问题有了些更好的认知。毕竟是之前学过的东西,还是比较好的。掌握程度:\(85\%^+\)离线分治算法具体是:线段树分治\(80\%^+\)就是个线段树上二分。CDQ分治基于时间的分治\(75\%^+\)基本......
  • [2024JZYZ暑期集训]知识点总结
    前言第三次暑期集训了,与前两次不同,这次没有前两次的激动了,所以也能够更深入地学习算法。闲话宿舍挺好,有空床能住。捡了三块钱,史上最灵异事件。R班好热闹。认识了几个郑州那边的大佬知识点Day1讲了几个基础数据结构(树状数,线段树),作业里面的题目很多之前都做过,就当复习了。......
  • 2024年pt市S组暑假集训游记
    记录而已,不必在意Day1上午第一天,一中的lzy老师把我们分配到一楼的机房,好,有沙发,有三个大空调,听说原来是一中的监控室。结果,我们去6楼等了好久,还是没有开课,然后我们就被叫去5楼听课了,火大。幸好听完课之后还是去一楼机房耍,开心。老师上课给我们复习了一些基础的东西,这......