首页 > 其他分享 >231009校内赛

231009校内赛

时间:2023-10-10 22:12:00浏览次数:45  
标签:校内 int top cin stk -- 231009 col

T1 里群

pPzkeDx.jpg

题解

阴间第一题

题目中有一个很明显的建图方法就是对于第 \(i\) 天入群的人在第 \(j\) 天退群

那么就在 \(i,j\) 之间连一条边

首先有一个结论,管理员个数不大于 \(3\)

对于这个结论,证明如下:

首先第一次删除出现后就一定需要两个管理员了

如果某次删除只删掉了某一个管理员添加的,那么另一个管理员当天值班就行

如果两个都删掉了,就需要第三个管理员

如果这时候某个管理员删的有三种,那么一定有一个管理的值班可以被替代

要删的区间内不可能每个管理都是天天删另外两个管理的人

因为这样的删除是必定会删除一天多一点或者两天的加入量的

在这段区间内的加入量赶不上删除量,总会有空出来可以替代的

自己多举点例子手模一下就可以了,不好描述清楚

所以无论如何都可以用三个管理员处理完所有情况

所以只需要分类讨论一下三种情况

如果只要一个管理就不能有删除

如果要两个管理那么按最上面的方法建的图就是一个二分图,判断是否为二分图即可

两种都不是那就是需要三个管理

对于任意两条边,每条边的两个端点分别组成一个区间

对于这两个区间只有不相交和包含两种关系,那么可以建一棵树来处理

每一个叶子节点就是一条边构成的区间,对于父节点来说,限制最紧的情况如下:

\([l,x_1],[x_1,x_2],[x_2,x_3],\cdots,[x_k-1,x_k],[x_k,r]\)

当然有可能中间的区间并没有拼接在一起

如果两端 \(l,r\) 分别是 \(1,2\) ,那么中间就可以用 \(3,1,3,1,3,1,\ldots\) 的方式拼接

算法就构建完了

#include<bits/stdc++.h>
#define N 100010
using namespace std;
int n,a[N],b[N],prea[N],preb[N],col[N],mx = 0,stk[N],top = 0;
vector<int>e[N],g[N];
bool flag = 0,tag = 1;
void pb(int x,int y){
	flag = 1;
	e[x].push_back(y);
	e[y].push_back(x);
	return ;
}
void dfs(int x,int c){
	col[x] = c;c^=1;
	for(int i : e[x]){
		if(col[i]!=-1){
			if(col[i]!=c){
				tag = 0;
				return ;
			}
			continue;
		}
		dfs(i,c);
		if(!tag) return ;
	}
}
int main(){
	freopen("group.in","r",stdin);
	freopen("group.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int T;cin>>T;
	while(T--){
		cin>>n;
		for(int i = 1;i<=n;i++){
			e[i].clear();
			g[i].clear();
			col[i] = -1;
		}
		for(int i = 1;i<=n;i++)
			cin>>a[i]>>b[i];
		flag = 0,tag = 1;top = 0;
		for(int i = 1;i<=n;i++)
			prea[i] = a[i],preb[i] = b[i];
		for(int i = 1;i<=n;i++){
			if(a[i]){
				while(b[stk[top]]<=a[i]&&a[i]>0){
					pb(stk[top],i);
					a[i]-=b[stk[top]];
					top--;
				}
				if(a[i]){
					b[stk[top]]-=a[i];
					pb(stk[top],i);
				}
			}
			if(b[i]) stk[++top] = i;
		}
		for(int i = 1;i<=n;i++)
			if(col[i]==-1) dfs(i,0);
		if(!flag){
			cout<<"1\n";
			for(int i = 1;i<=n;i++)
				cout<<"1 ";
			cout<<"\n";
			continue;
		}
		if(tag){
			cout<<"2\n";
			for(int i = 1;i<=n;i++)
				cout<<col[i]+1<<" ";
			cout<<"\n";
			continue;
		}
		for(int i = 1;i<=n;i++)
			a[i] = prea[i],b[i] = preb[i];
		top = 0;
		for(int i = 1;i<=n;i++){
			if(a[i]){
				while(b[stk[top]]<=a[i]&&a[i]>0){
					g[i].push_back(stk[top]);
					a[i]-=b[stk[top]];
					top--;
				}
				if(a[i]) b[stk[top]]-=a[i];
			}
			stk[++top] = i;
		}
		for(int i = 1;i<=n;i++) col[i] = 0;
		for(int i = 1;i<=top;i++)
			col[stk[i]] = (i&1);
		for(int i = n;i>=1;i--){
			int u = col[stk[top]];top--;
			int v = col[stk[top]],pos = 0,tmp = 0;
			if(u==v) v++;
			for(int j = 0;j<=2;j++)
				if(j!=u&&j!=v) pos = j;
			if(!g[i].size()) continue;
			int idx[2] = {pos,v};
			for(int j = g[i].size()-1;j>=0;j--){
				int x = g[i][j];
				stk[++top] = x;
				col[x] = idx[tmp];
				tmp^=1;
			}
		}
		cout<<"3\n";
		for(int i = 1;i<=n;i++)
			cout<<col[i]+1<<" ";
		cout<<"\n";
	}
	return 0;
}

有亿点点长

T2 xormex

pPzVlPU.jpg

题解

打表特判题,恶心吐了

通过打表可以发现强制 \(0\) 在最开头

这样可以使 \(xormex\) 变成了所有前缀 \(mex\) 的异或和,不是区间 \(mex\) 了,因为其他区间都为 \(0\)

不过需要特判一下 \(3 \ 2\) 的情况

再说判断无解

对于 \(n = 2^m,k<n\) 的情况一定无解,因为没有办法消除掉最高位的 \(1\) 而 \(k\) 最高位为 \(0\)

设数组 \(b_i\) 表示\([1,i]\) 的前缀 \(mex\) 和,明显有 \(b_1 = 1,b_n = n\)

设 $t = n \oplus 1 \oplus k $ , 只需要让 \((1,n)\) 区间内的 \(b\) 的异或和等于 \(t\) 就行了

大多数情况下,直接把 \(t\) 二进制拆位,然后把每一位从小到大放在 \(b\) 的最后几个位置即可。

问题在于对于前面几个贡献只有 \(1\) 的位置,如果有奇数个这样的位置, 就会导致异或和有 \(1\) 的差距

只需将第一个贡献不为 \(1\) 的位置改为 \(x \oplus 1\) 即可

对于最后一位是 \(n+1\) 的情况也需要特判,将最后三位改为 \(2,3,n\)

这道题总之就是特判就完了

对于 \(b\) 数组的还原就很简单了

#include<bits/stdc++.h>
#define N 140010
using namespace std;
int n,k,mex[N],b[N],a[N];
int popcount(int u){
	u = (u&0x55555555)+((u>>1)&0x55555555);
	u = (u&0x33333333)+((u>>2)&0x33333333);
	u = (u&0x0f0f0f0f)+((u>>4)&0x0f0f0f0f);
	u = (u&0x00ff00ff)+((u>>8)&0x00ff00ff);
	u = (u&0x0000ffff)+((u>>16)&0x0000ffff);
	return u;
}
int main(){
	freopen("xormex.in","r",stdin);
	freopen("xormex.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int T;cin>>T;
	while(T--){
		cin>>n>>k;
		int mx = 1;
		while(mx*2<=n) mx*=2;
		if(k>2*mx-1){
			cout<<"-1\n";
			continue;
		}
		if(popcount(n)==1&&k<n){
			cout<<"-1\n";
			continue;
		}
		if((n==2&&k==2)||(n==3&&k==2)){
			cout<<"-1\n";
			continue;
		}
		if(n==3&&k==1){
			cout<<"1 0 2\n";
			continue;
		}
		if((n%4==0&&k==n)||(n%4==1&&k==1)){
			for(int j = 0;j<n;j++)
				cout<<j<<" ";
			cout<<"\n";
			continue;
		}
		if(n%4==2&&k==n){
			for(int j = 0;j+2<n;j++)
				cout<<j<<" ";
			cout<<n-1<<" "<<n-2<<"\n";
			continue;
		}
		for(int i = 1;i<n;i++)
			mex[i] = 1;
		mex[n] = n;b[0] = 0;
		int u = (n^1^k);
		while(u){
			b[++b[0]] = (u&-u);
			u-=(u&-u);
		}
		for(int i = b[0];i;i--)
			mex[n-b[0]+i-1] = b[i];
		if(n>=5&&n%2==1&&k==n-1)
			mex[n-1] = 3,mex[n-2] = 2;
		int t = 0;
		for(int i = 1;i<=n;i++) t^=mex[i];
		if(t!=k){
			for(int i = 2;i<=n;i++){
				if(mex[i]!=1){
					mex[i]^=1;
					break;
				}
			}
		}
		for(int i = 1;i<=n;i++)
			a[mex[i]] = 1;
		cout<<"0 ";
		for(int i = 2,j = 1;i<=n;i++){
			if(mex[i]==1){
				while(a[j]) j++;
				cout<<j<<" ";
				j++;
			}else cout<<mex[i-1]<<" ";
		}
		cout<<"\n";
		for(int i = 0;i<=n;i++) a[i] = 0;
	}
	return 0;
}

T3 可重集计数

pPz3Fjf.jpg

题解

不是很会,直接贴题解

主要不是很明白容斥中 \(f\) 数组的表示

pPz3EDS.jpg

#include<bits/stdc++.h>
#define N 4010
using namespace std;
int n,m,k,mod,f[N][N],g[N][N],mx[N];
int getans(int m,int k){
	if(k>mx[m]) return 0;
	if(k<=m) return f[k][n];
	int ans = 0,fl = 1;
	for(int j = 0;j*(m+1)<=k;j++){
		for(int x = j*(j+1)/2;x*(m+1)<=n;x++)
			if(j&1) ans = (ans+1ll*(mod-g[j][x])*f[k-j*(m+1)][n-x*(m+1)])%mod;
			else ans = (ans+1ll*g[j][x]*f[k-j*(m+1)][n-x*(m+1)])%mod;
		fl = mod-fl;
	}
	return ans;
}
int main(){
	freopen("multiset.in","r",stdin);
	freopen("multiset.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>mod;
	f[0][0] = g[0][0] = 1;
	for(int i = 1;i<=n;i++)
		for(int j = i;j<=n;j++)
			f[i][j] = (f[i-1][j-1]+f[i][j-i])%mod;
	for(int i = 1;i<=n;i++)
		for(int j = i*(i+1)/2;j<=n;j++)
			g[i][j] = (g[i-1][j-i]+g[i][j-i])%mod;
	for(m = 1;m<=n;m++){
		int tmp = 0,ti = 0;
		for(int i = 1;i<=n&&tmp<=n;i++)
			for(int j = 1;j<=m&&tmp<=n;j++)
				tmp+=i,ti++;
		if(tmp<=n) ti = n;
		mx[m] = ti;
	}
	long long sum = 0;
	for(int i = 1;i<=n;i++)
		for(int j = 1;j<=n;j++)
			sum+=getans(i,j);
	cout<<sum;
	return 0;
}

T4

照例,不会,前三题都那样了还想T4?

标签:校内,int,top,cin,stk,--,231009,col
From: https://www.cnblogs.com/cztq/p/17755866.html

相关文章

  • 20231009打卡
    早上,我计划学习手工焊接电路板。作为打卡的第一项任务,我仔细阅读了焊接指南,并准备好所需的工具和材料。我了解到电路板设计和制作的重要性,因为它们是软件工程师日后开发硬件设备所需的基础。我按照指南的步骤进行焊接,将电子元件精确地连接到电路板上。这需要仔细的操作和耐心,但我......
  • LY1380 [ 20231009 NOIP 模拟赛 T1 ] AK 神
    题意给定长度为\(n\)的序列\(S\)。\(A\),\(B\)两人轮流取连续\(k\)个数,保证\(n\equiv1\pmodk\)。\(A\)使最终数字更小,\(B\)使最终数字更大。问取到数的和。Sol直接考虑每次选哪些数,怎么选显然是不好做的。不难发现\(n\equiv1\pmodk\)的条件。题面提示我们......
  • 231007校内赛
    T1karma题解首先从贪心的思路出发把所有零多的字符串放在前面,但如下一组数据便可以卡掉201100接着我们可以来思考对于贪心的更改多举几组不同的可以卡掉的样例后可以发现如下规律先将所有字符串按\(0\)的数量排一遍序对于每一个字符串的\(0\)和\(1\)的数量我......
  • 20231009 模拟赛总结
    模拟赛链接排名:\(\text{rank1}\)分数:\(100+100+70+20=290\)终于有一次模拟赛不掉分了。T1:最后一课/dist题目描述:在一个平面直角坐标系上,给定一条直线\(y=k\)和两个点\(P(x_1,y_1),Q(x_2,y_2)\),求经过水平线的两点的最短距离。(\(k,x_1,y_1,x_2,y_2\le5\times10^8\))思......
  • 华为云OBS配置-远程附件-20231009
    使用此服务前请先注册并绑定华为云官方合作伙伴账号,享受VIP服务和优惠价格(新购和续费都有专属折扣),更能领取大额代金券!  立即注册/已有账号绑定=>>! 如果不能绑定,请联系售前商务或工单联系售后处理!  创建华为云存储OBS步骤: 一、进入OBS控制台:https://storage.huawei......
  • 随笔20231009
    诺贝尔经济学奖获得者弗里德曼说:花自己的钱办自己的事,最为经济;花自己的钱给别人办事,最有效率;花别人的钱为自己办事,最为浪费;花别人的钱为别人办事,最不负责任。花自己的钱办自己的事,既讲节约,又讲效果;花自己的钱,办别人的事,只讲节约,不讲效果;花别人的钱,办自己的事,只讲效果,不讲节约;花别......
  • 231004校内赛
    T1水管题解很简单的一道题,别想复杂了只要一边\(dfs\)即可先将当前点的所有水量给出去,如果缺水就给出去负数那么等到最后一个节点如果不是刚好合适,那么就把剩余水量回溯回来,无论正负再如此给下一个连边的点如果最后一个点刚好合适那么给下一个点的就是\(0\)实现很简单......
  • 231002校内赛
    T1数独题解十分简单的一道模拟题有sb少打了一个换行挂50分#include<bits/stdc++.h>#defineN15usingnamespacestd;structnode{ inta[N][N],be;}t[N*10];intT,n=9,q;intferror(intcnt,intx,inty,intk){ for(inti=1;i<=n;i++) if(t[cnt].a[x][i]==k)......
  • 230930校内赛
    T1洛阳怀题解首先非常容易求出的是所有的\(\gcd\)对于\(\gcd\)而言,如果它的分数是负数,那么将它除去一定会使这个数列得分变大所以只用求出所有的\(\gcd\)的分数并判断正负以及是否除过当前答案了就可以了还有一点是因为\(\gcd\)是单调不降的,所以可以从后往前查保证......
  • 2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛(同步赛)
    A.AXorBProblem(计数)输入511223输出9说明点击查看代码#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false);cin.tie(0),cout.tie(0)#defineintlonglongusingnamespacestd;constintN=2e5+10;unordered_map<int,int>......