2021-09-04模拟赛

2021-09-04模拟赛

今天爆零了,感觉很不应该,也许是没有进入状态,或者是有点飘了
首先在战略上我没有转到模拟得分战略,而是尝试先去切题,这和昨天讲的背道而驰
在战术上我没有及时转移
首先把题全都看一遍就应该意识到这次模拟不会那么简单,应该以得分为主以暴力为主,但是在看到T2的时候感觉自己能切,还是没忍住去写了链表,但是接近写完的时候才发现这么写的话IC操作时间复杂度是假的,不得已只能改变原有写法,利用现有代码写20分暴力,这期间debug耗了很长时间,但是就一直耗着,没有及时转移
接着我又没有去利用本来已经不多的时间去尽快写了暴力,而是费尽心思去想T1规律,花了很长时间找规律,导致时间已经不足以写完矩阵快速幂,就急急忙忙写了40分,这时才想起来去写T3T4暴力,但时间已经不够了
成绩出了之后,爆零了
下午仔细分析了一下,发现T3T4依然不太可做,但是T1T2应该能拿200
首先针对我研究了很长时间的T2链表做法
20分:
强行二维链表,记录每个点上下左右点的坐标,更新时分别维护横纵最值,输出时遍历即可
但是出问题了
经过大量的数据对拍,可以发现一个问题:当操作数大于矩阵边长的时候就没对过,那么为什么呢
单独上下操作或者左右操作都没有问题,那么问题就只可能出在输出上了,仔细看看输出,也没什么问题
那么是什么问题呢,我们可以发现,在矩阵边长以下的变换是正确的,并且输出进行的操作居然只有矩阵边长次
这是我就隐隐意识到不大对劲,估计是进行操作的时候出大问题
一看,不就是嘛,应该进行m次操作,循环上写的n
0分代码:

#include<bits/stdc++.h>
#define N 1005
#define M 1000005
#define ll long long
#define fn(i,st,ed) for(int i=st;i<=ed;i++)
#define fd(i,st,ed) for(int i=st;i>=ed;i--)
#define fg(i,x) for(int i=head[x];~i;i=e[i].nxt)
#define pa pair<int,int>
#define mkp(x,y) make_pair(x,y)
using namespace std;
inline int read(){
    
    
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){
    
    x=x*10+c-'0';c=getchar();}
	return x*f;
}
class Link_List{
    
    
	public:
		void build(int n){
    
    
			fn(i,1,n)fn(j,1,n){
    
    
				if(i==1){
    
    
					if(j==1){
    
    
						L[1][1]=mkp(1,n);
						R[1][1]=mkp(1,2);
						U[1][1]=mkp(n,1);
						D[1][1]=mkp(2,1);
						continue;
					}
					if(j==n){
    
    
						L[1][n]=mkp(1,n-1);
						R[1][n]=mkp(1,1);
						U[1][n]=mkp(n,n);
						D[1][n]=mkp(2,n);
						continue;	
					}
					L[1][j]=mkp(1,j-1);
					R[1][j]=mkp(1,j+1);
					U[1][j]=mkp(n,j);
					D[1][j]=mkp(2,j);
					continue;
				}
				if(i==n){
    
    
					if(j==1){
    
    
						L[n][1]=mkp(n,n);
						R[n][1]=mkp(n,2);
						U[n][1]=mkp(n-1,1);
						D[n][1]=mkp(1,1);
						continue;
					}
					if(j==n){
    
    
						L[n][n]=mkp(n,n-1);
						R[n][n]=mkp(n,1);
						U[n][n]=mkp(n-1,n);
						D[n][n]=mkp(1,n);
						continue;	
					}
					L[n][j]=mkp(n,j-1);
					R[n][j]=mkp(n,j+1);
					U[n][j]=mkp(n-1,j);
					D[n][j]=mkp(1,j);
					continue;
				}
				if(j==1){
    
    
					L[i][1]=mkp(i,n);
					R[i][1]=mkp(i,2);
					U[i][1]=mkp(i-1,1);
					D[i][1]=mkp(i+1,1);
					continue;
				}
				if(j==n){
    
    
					L[i][n]=mkp(i,n-1);
					R[i][n]=mkp(i,1);
					U[i][n]=mkp(i-1,n);
					D[i][n]=mkp(i+1,n);
					continue;	
				}
				L[i][j]=mkp(i,j-1);
				R[i][j]=mkp(i,j+1);
				U[i][j]=mkp(i-1,j);
				D[i][j]=mkp(i+1,j);
			}
			l=1,r=n,u=1,d=n;
		}
		void RC(){
    
    
			l=L[1][l].second;
			r=L[1][r].second;
		}
		void LC(){
    
    
			l=R[1][l].second;
			r=R[1][r].second;	
		}
		void UC(){
    
    
			u=D[u][1].first;
			d=D[d][1].first;
		}
		void DC(){
    
    
			u=U[u][1].first;
			d=U[u][1].first;	
		}
	protected:
		pa L[N][N],R[N][N],U[N][N],D[N][N];
		int a[N][N];
		int l,r,u,d;
};
class solution:protected Link_List{
    
    
	public:
		void init(){
    
    
			n=read(),m=read();
			fn(i,1,n)fn(j,1,n)a[i][j]=read();
			scanf("%s",operation);
			build(n);
		}
		void solve(){
    
    
			fn(i,0,n-1){
    
    //这里应该是m-1
				if(operation[i]=='R')RC();
				if(operation[i]=='L')LC();
				if(operation[i]=='U')UC();
				if(operation[i]=='D')DC();
			}
			for(int x=u,y;;){
    
    
				for(y=l;;){
    
    
					printf("%d ",a[x][y]);
					if(y==r)break;
					y=R[x][y].second;	
				}
				printf("\n");
				if(x==d)break;
				x=D[x][y].first;
			}
		}
	private:
		int n,m;
		char operation[M];
}S;
int main(){
    
    
	freopen("mat.in","r",stdin);
	freopen("mat.out","w",stdout);
	S.init();S.solve();
	return 0;	
}

20分代码:

#include<bits/stdc++.h>
#define N 1005
#define M 1000005
#define ll long long
#define fn(i,st,ed) for(int i=st;i<=ed;i++)
#define fd(i,st,ed) for(int i=st;i>=ed;i--)
#define fg(i,x) for(int i=head[x];~i;i=e[i].nxt)
#define pa pair<int,int>
#define mkp(x,y) make_pair(x,y)
using namespace std;
inline int read(){
    
    
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){
    
    x=x*10+c-'0';c=getchar();}
	return x*f;
}
class Link_List{
    
    
	public:
		void build(int n){
    
    
			fn(i,1,n)fn(j,1,n){
    
    
				if(i==1){
    
    
					if(j==1){
    
    
						L[1][1]=mkp(1,n);
						R[1][1]=mkp(1,2);
						U[1][1]=mkp(n,1);
						D[1][1]=mkp(2,1);
						continue;
					}
					if(j==n){
    
    
						L[1][n]=mkp(1,n-1);
						R[1][n]=mkp(1,1);
						U[1][n]=mkp(n,n);
						D[1][n]=mkp(2,n);
						continue;	
					}
					L[1][j]=mkp(1,j-1);
					R[1][j]=mkp(1,j+1);
					U[1][j]=mkp(n,j);
					D[1][j]=mkp(2,j);
					continue;
				}
				if(i==n){
    
    
					if(j==1){
    
    
						L[n][1]=mkp(n,n);
						R[n][1]=mkp(n,2);
						U[n][1]=mkp(n-1,1);
						D[n][1]=mkp(1,1);
						continue;
					}
					if(j==n){
    
    
						L[n][n]=mkp(n,n-1);
						R[n][n]=mkp(n,1);
						U[n][n]=mkp(n-1,n);
						D[n][n]=mkp(1,n);
						continue;	
					}
					L[n][j]=mkp(n,j-1);
					R[n][j]=mkp(n,j+1);
					U[n][j]=mkp(n-1,j);
					D[n][j]=mkp(1,j);
					continue;
				}
				if(j==1){
    
    
					L[i][1]=mkp(i,n);
					R[i][1]=mkp(i,2);
					U[i][1]=mkp(i-1,1);
					D[i][1]=mkp(i+1,1);
					continue;
				}
				if(j==n){
    
    
					L[i][n]=mkp(i,n-1);
					R[i][n]=mkp(i,1);
					U[i][n]=mkp(i-1,n);
					D[i][n]=mkp(i+1,n);
					continue;	
				}
				L[i][j]=mkp(i,j-1);
				R[i][j]=mkp(i,j+1);
				U[i][j]=mkp(i-1,j);
				D[i][j]=mkp(i+1,j);
			}
			l=1,r=n,u=1,d=n;
		}
		void RC(){
    
    
			l=L[1][l].second;
			r=L[1][r].second;
		}
		void LC(){
    
    
			l=R[1][l].second;
			r=R[1][r].second;	
		}
		void UC(){
    
    
			u=D[u][1].first;
			d=D[d][1].first;
		}
		void DC(){
    
    
			u=U[u][1].first;
			d=U[u][1].first;	
		}
	protected:
		pa L[N][N],R[N][N],U[N][N],D[N][N];
		int a[N][N];
		int l,r,u,d;
};
class solution:protected Link_List{
    
    
	public:
		void init(){
    
    
			n=read(),m=read();
			fn(i,1,n)fn(j,1,n)a[i][j]=read();
			scanf("%s",operation);
			build(n);
		}
		void solve(){
    
    
			fn(i,0,m-1){
    
    
				if(operation[i]=='R')RC();
				if(operation[i]=='L')LC();
				if(operation[i]=='U')UC();
				if(operation[i]=='D')DC();
			}
			for(int x=u,y;;){
    
    
				for(y=l;;){
    
    
					printf("%d ",a[x][y]);
					if(y==r)break;
					y=R[x][y].second;	
				}
				printf("\n");
				if(x==d)break;
				x=D[x][y].first;
			}
		}
	private:
		int n,m;
		char operation[M];
}S;
int main(){
    
    
	freopen("mat.in","r",stdin);
	freopen("mat.out","w",stdout);
	S.init();S.solve();
	return 0;	
}

100分:
显然对于上下和左右的操作,相反的操作是可以抵消的,而IC操作其实就是将权值与位置互换,我们可以设置一个状态,当出现IC操作的时候,我们转到这个状态上,之后的上下左右操作则需要在这个状态下进行记录,统计答案时则根据状态转移每个点
100分代码:

#include<bits/stdc++.h>
#define N 1005
#define M 1000005
#define ll long long
#define fn(i,st,ed) for(int i=st;i<=ed;i++)
#define fd(i,st,ed) for(int i=st;i>=ed;i--)
#define fg(i,x) for(int i=head[x];~i;i=e[i].nxt)
#define pa pair<int,int>
#define mkp(x,y) make_pair(x,y)
using namespace std;
inline int read(){
    
    
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){
    
    x=x*10+c-'0';c=getchar();}
	return x*f;
}
char operation[M],a[N][N],ans[N][N],now[4]={
    
    0,1,2,3},addition[4];
int main(){
    
    
	int n=read(),m=read();
	fn(i,1,n)fn(j,1,n)a[i][j]=read();
	scanf("%s",operation+1);
	fn(i,1,m){
    
    
		char c=opeartion[i];
		if(c=='R')add[now[2]]++;
		if(c=='L')add[now[2]]--;
		if(c=='D')add[now[1]]++;
		if(c=='U')add[now[1]]--;
		if(c=='I')swap(now[2],now[3]);
		if(c=='C')swap(now[1],now[3]);
	}
	fn(i,1,n)fn(j,1,n){
    
    
		int t[4]={
    
    0,i,j,a[i][j]};
		fn(k,1,3)t[k]=((t[k]+add[k]-1)%n+n)%n+1;
		ans[t[now[1]]][t[now[2]]]=t[now[3]];
	}
	fn(i,1,n){
    
    fn(j,1,n)printf("%d ",ans[i][j]);printf("\n");}
	return 0;
}

对于T2,我们可以得出一点教训,不要相信样例,因为很水,自己出数据一定要出大一点,出的刁钻一点
接下来去看T1
T1我的递推式子是没有错的,那么问题会出在哪里呢,我一打开代码就看到了,我求出的递推值根本就没用到
0分代码:

#include<bits/stdc++.h>
#define M 10000005
#define mod 1000000007
#define ll long long
#define fn(i,st,ed) for(int i=st;i<=ed;i++)
#define fd(i,st,ed) for(int i=st;i>=ed;i--)
#define fg(i,x) for(int i=head[x];~i;i=e[i].nxt)
#define pa pair<int,int>
#define mkp(x,y) make_pair(x,y)
using namespace std;
inline ll read(){
    
    
	ll x=0,f=1;char c=getchar();
	while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){
    
    x=x*10+c-'0';c=getchar();}
	return x*f;
}
ll x[M],f[M],ans;
int main(){
    
    
	//freopen("per.in","r",stdin);
	//freopen("per.out","w",stdout);
	f[1]=1,f[2]=1,f[3]=2,f[4]=4;
	x[1]=x[2]=x[3]=x[4]=0;
	fn(i,5,M-1){
    
    x[i]=x[i-1]+f[i-3];f[i]=(x[i]+i)%mod;}
	int t=read();
	while(t--){
    
    
		ll x=read();
		ans=ans^x;//这里出大问题
	}
	printf("%lld\n",ans);
	return 0;
}

40分代码:

#include<bits/stdc++.h>
#define M 10000005
#define mod 1000000007
#define ll long long
#define fn(i,st,ed) for(int i=st;i<=ed;i++)
#define fd(i,st,ed) for(int i=st;i>=ed;i--)
#define fg(i,x) for(int i=head[x];~i;i=e[i].nxt)
#define pa pair<int,int>
#define mkp(x,y) make_pair(x,y)
using namespace std;
inline ll read(){
    
    
	ll x=0,f=1;char c=getchar();
	while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){
    
    x=x*10+c-'0';c=getchar();}
	return x*f;
}
ll x[M],f[M],ans;
int main(){
    
    
	//freopen("per.in","r",stdin);
	//freopen("per.out","w",stdout);
	f[1]=1,f[2]=1,f[3]=2,f[4]=4;
	x[1]=x[2]=x[3]=x[4]=0;
	fn(i,5,M-1){
    
    x[i]=x[i-1]+f[i-3];f[i]=(x[i]+i)%mod;}
	int t=read();
	while(t--){
    
    
		ll x=read();
		ans=ans^f[x];
	}
	printf("%lld\n",ans);
	return 0;
}

100分:
使用矩阵快速幂进行优化,没什么可说的,根本就是时间不够了
代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100;
const int mod=1e9+7;
#define ll long long
int n,m;
ll f[N];
ll ans;
struct matrix{
    
    
	ll a[5][5];
	int x,y;	
};
void print(matrix o){
    
    
	printf("------\n");
	for(int i=1;i<=o.x;i++){
    
    
		for(int j=1;j<=o.y;j++) printf("%lld ",o.a[i][j]);
		printf("\n");
	}
	printf("\n");
}
matrix mul(matrix u,matrix v){
    
    
	matrix ans;
	ans.x=u.x,ans.y=v.y;
	for(int i=1;i<=ans.x;i++){
    
    
		for(int j=1;j<=ans.y;j++){
    
    
			ans.a[i][j]=0;
			for(int k=1;k<=u.y;k++) ans.a[i][j]=(ans.a[i][j]+u.a[i][k]*v.a[k][j])%mod;
		}
	}
	return ans;
}
int pre[5][5]={
    
    {
    
    },{
    
    0,1,0,0,0},{
    
    0,1,0,0,1},{
    
    0,0,1,0,0},{
    
    0,1,0,1,1}};
matrix tr;
matrix ksm(matrix o,int k){
    
    
	matrix ans;
	ans.x=ans.y=o.x;
	for(int i=1;i<=o.x;i++)
		for(int j=1;j<=o.x;j++) ans.a[i][j]=i==j;
	while(k){
    
    
		if(k&1) ans=mul(ans,o);
		o=mul(o,o);
		k>>=1;
	}
	return ans;
}
matrix lst;
int main(){
    
    
	//freopen("per.in","r",stdin);
	//freopen("per.out","w",stdout);
	tr.x=tr.y=4;
	for(int i=1;i<=4;i++){
    
    
		for(int j=1;j<=4;j++) tr.a[i][j]=pre[i][j];
	}
	lst.x=1,lst.y=4;
	lst.a[1][1]=3;lst.a[1][2]=1;lst.a[1][3]=1;lst.a[1][4]=1;
	int T;
	scanf("%d",&T);
	ll tot=0;
	while(T--){
    
    
		ll oo;
		scanf("%d",&n);
		if(n==1) oo=1;
		else if(n==2) oo=1;
		else if(n==3) oo=2;
		else{
    
    
			matrix res=ksm(tr,n-3);
			matrix ans=mul(lst,res);
			oo=(ans.a[1][1]-ans.a[1][3]+mod)%mod;
		}
		tot^=oo;
	}
	printf("%lld",tot);
}

今天也算是一个时间节点吧,这次模拟可以给我一个比较深刻的教训
既然打算大量投入时间在竞赛上,就应该去认真对待,而不是这错一点小错误,那错一点小错误,时间上根本没进入模拟状态,应该每次模拟都认真对待,不要轻信样例,要多多自己去造数据,不要死扣一个题,先写暴力在想去切,每个题都尝试着写一写,不要连写都不写
这些问题以后都不要出现,不然是走不长远的

猜你喜欢

转载自blog.csdn.net/MuLaSaMe/article/details/120101563