联赛模拟11题解

好久没写博客了,模拟赛、联考也进行了好多,从今天开始总结。

T1 One

Solution

1种是网上的线性解法,将其编号0~n-1,从后往前推,ans最后一轮为0,每次(ans+=n-i+1)%=i,即加上这一轮应该死的人的报号再模上一轮的人数

还有一种是求出每轮某人死的时候他排在第几位(在上一轮剩下的人里),比如12345,3死了,排第三位,第二次4死了,他也排第3位。
最后一个剩下的肯定排第一位(only one left),然后看看前面死了的人有谁位置比他靠前,有就++(可能好理解一些)

// solutione_1
#include <cstdio>
#define rint register int
const int maxn=1e7+5;
int n,ans,cs;
int main(){
	//freopen("1.in","r",stdin);
	freopen("one.in","r",stdin);
	freopen("one.out","w",stdout);
	scanf("%d",&cs);
	while(cs--){
		scanf("%d",&n); ans=0;
		for(rint i=2;i<=n;++i) (ans+=n-i+1)%=i;
		printf("%d\n",ans+1);
	}
	return 0;
}

#include <cstdio>
#define rint register int
const int maxn=1e7+5;
int p[maxn],n,ans;
int main(){
	//freopen("1.in","r",stdin);
	freopen("one.in","r",stdin);
	freopen("one.out","w",stdout);
	rint cs; scanf("%d",&cs);
	while(cs--){
		scanf("%d",&n);
		p[1]=1;
		for(rint i=2;i<n;++i){
			p[i]=(p[i-1]-2+i)%(n-i+1)+1;
		/*	p[i]=(p[i-1]-1+i)%(n-(i-1));
			if(!p[i]) p[i]=(n-(i-1));
			*/
		}
		ans=1;
		for(rint i=n-1;i>=1;--i) if(p[i]<=ans) ans++;
		printf("%d\n",ans);
	}
	return 0;
}

T2 砖块

Solution

小模拟,没啥好说的



#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define rint register int
using namespace std;
const int maxn=1e2+5,INF=0x3f3f3f3f;
int k,op,tot,ans,x[maxn][15],y[maxn][15],mp[2000+1][2000+1];
char s[maxn];
int main(){
	//freopen("1.in","r",stdin);
	//freopen("1.out","w",stdout);
	freopen("block.in","r",stdin);
	freopen("block.out","w",stdout);
	int cs;scanf("%d",&cs);
	while(cs--){
		scanf("%d%s",&k,s+1);
		tot=strlen(s+1);
		for(rint i=1;i<=tot;++i){
			for(rint j=1;j<=k;++j){
				x[i][j]=-INF;
				y[i][j]=-INF;
			}
		}
		memset(mp,0,sizeof mp);
		mp[1000][1000]=ans=1;
		op=1;
		for(rint i=1;i<=tot;++i){
			if(op==1){
				if(s[i]=='N'){
					for(rint j=1;j<=k;++j) x[i][j]=x[i-1][1],y[i][j]=y[i-1][1]+j;
				}
				else if(s[i]=='S'){
					for(rint j=1;j<=k;++j) x[i][j]=x[i-1][1],y[i][j]=y[i-1][1]-j;
				}
				else if(s[i]=='W'){
					for(rint j=1;j<=k;++j) x[i][j]=x[i-1][1]-j,y[i][j]=y[i-1][1];
				}
				else if(s[i]=='E'){
					for(rint j=1;j<=k;++j) x[i][j]=x[i-1][1]+j,y[i][j]=y[i-1][1];
				}
				for(rint j=1;j<=k;++j) ans=max(ans,++mp[1000+x[i][j]][1000+y[i][j]]);
				op=2;
			}
			else{
				if(y[i-1][1]==y[i-1][2]){
					if(s[i]=='N'){
						for(rint j=1;j<=k;++j) x[i][j]=x[i-1][j],y[i][j]=y[i-1][j]+1;
					}
					else if(s[i]=='S'){
						for(rint j=1;j<=k;++j) x[i][j]=x[i-1][j],y[i][j]=y[i-1][j]-1;
					}
					else if(s[i]=='W'){
						rint lefx=INF;
						for(rint j=1;j<=k;++j) lefx=min(lefx,x[i-1][j]);
						y[i][1]=y[i-1][1];
						x[i][1]=lefx-1;
						op=1;
					}
					else if(s[i]=='E'){
						rint rigx=-INF;
						for(rint j=1;j<=k;++j) rigx=max(rigx,x[i-1][j]);
						y[i][1]=y[i-1][1];
						x[i][1]=rigx+1;
						op=1;
					}
					if(op==1) ans=max(ans,++mp[1000+x[i][1]][1000+y[i][1]]);
					else for(rint j=1;j<=k;++j) ans=max(ans,++mp[1000+x[i][j]][1000+y[i][j]]);
				}
				else{
					if(s[i]=='N'){
						rint uy=-INF;
						for(rint j=1;j<=k;++j) uy=max(uy,y[i-1][j]);
						x[i][1]=x[i-1][1];
						y[i][1]=uy+1;
						op=1;
					}
					else if(s[i]=='S'){
						rint dy=INF;
						for(rint j=1;j<=k;++j) dy=min(dy,y[i-1][j]);
						x[i][1]=x[i-1][1];
						y[i][1]=dy-1;
						op=1;
					}
					else if(s[i]=='W'){
						for(rint j=1;j<=k;++j) y[i][j]=y[i-1][j],x[i][j]=x[i-1][j]-1;
					}
					else if(s[i]=='E'){
						for(rint j=1;j<=k;++j) y[i][j]=y[i-1][j],x[i][j]=x[i-1][j]+1;
					}
					if(op==1) ans=max(ans,++mp[1000+x[i][1]][1000+y[i][1]]);
					else for(rint j=1;j<=k;++j) ans=max(ans,++mp[1000+x[i][j]][1000+y[i][j]]);
				}
			}
		}
		if(op==1) printf("%d\n%d\n%d\n",x[tot][1],y[tot][1],ans);
		else{
			sort(x[tot]+1,x[tot]+1+k);
			sort(y[tot]+1,y[tot]+1+k);
			printf("%d",x[tot][1]);
			for(rint i=2;i<=k;++i) printf(" %d",x[tot][i]);
			printf("\n%d",y[tot][1]);
			for(rint i=2;i<=k;++i) printf(" %d",y[tot][i]);
			printf("\n%d\n",ans);
		}
	}
	return 0;
}

T3 数字

等我搞完exLucas再说

T4

Solution

考场上想到了哈希,但带乘带加的线段树没调出来,只能交了一个\(n^2\)的暴力,不过2个循环就跑了70......数据不强
但还是挺可惜的。
对于甜圈,只有唯一的合法操作序列,我们将这个序列做一下字符串哈希。
然后对于每次修改,区间乘base,加区间加val,最后查询多少数的hash值符合要求即可

Code

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cmath>
#include <cctype>
#define rint register int
#define L (rt*2)
#define R (rt*2+1)
char buf[1<<20],*p1,*p2;
#define gc() (p1==p2?(p2=buf+fread(p1=buf,1,1<<20,stdin),p1==p2?EOF:*p1++):*p1++)
#define read() ({\
	rint x=0; register bool f=0; register char ch=gc();\
	while(!isdigit(ch)) f|=ch=='-',ch=gc();\
	while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch&15),ch=gc();\
	f?-x:x;\
})
using namespace std;
typedef unsigned long long ull;
const int maxn=2e5+5;
const ull bs=13331;
int n,k,t,ans,l[maxn],r[maxn],d[maxn];
ull val[maxn],st;
bool pd=1;
ull w[maxn*4],lj[maxn*4],lc[maxn*4];
void down(rint rt,rint l,rint r,rint mid){
	w[L]=w[L]*lc[rt]+lj[rt];
	w[R]=w[R]*lc[rt]+lj[rt];
	lj[L]=lj[L]*lc[rt]+lj[rt];
	lj[R]=lj[R]*lc[rt]+lj[rt];
	lc[L]*=lc[rt];
	lc[R]*=lc[rt];
	lj[rt]=0;lc[rt]=1;
}
void B(rint rt,rint l,rint r){
	lc[rt]=1;
	if(l==r) return;
	rint mid=(l+r)/2;
	B(L,l,mid);
	B(R,mid+1,r);
}
void modify(rint rt,rint l,rint r,rint a,rint b,ull x){
	if(a<=l&&r<=b){
		lj[rt]=lj[rt]*bs+x;
		lc[rt]*=bs;
		w[rt]=w[rt]*bs+x;
		return;
	}
	rint mid=(l+r)/2;
	down(rt,l,r,mid);
	if(a<=mid) modify(L,l,mid,a,b,x);
	if(b >mid) modify(R,mid+1,r,a,b,x);
}
void query(rint rt,rint l,rint r){
	if(l==r) return ans+=(w[rt]==st),void();
	rint mid=(l+r)/2;
	down(rt,l,r,mid);
	query(L,l,mid),query(R,mid+1,r);
}
int main(){
	freopen("deco.in","r",stdin);
	freopen("deco.out","w",stdout);
	n=read(),k=read(),t=read();
	for(rint i=1;i<=k;++i) st=st*bs+i;
	B(1,1,n);
	for(rint i=1;i<=t;++i){
		const rint l=read(),r=read(),d=read();
		modify(1,1,n,l,r,d);
	}
	query(1,1,n);
	printf("%d\n",ans);
	return 0;
}

posted @ 2020-10-09 06:40  liuzhaoxu  阅读(157)  评论(1编辑  收藏  举报