251. 8.1 CSP-S NOIP储备营比赛 题面+代码

T1 数字拆分

题目内容

给定\(k\)个实数\(r_i\),每次拆分你可以选择一个\(r_i\),把一个数字\(x\)拆成\(\lfloor xr_i\rfloor\)\(x-\lfloor xr_i\rfloor\)两部分,请判断整数\(n\)能否通过若干次拆分得到整数\(m\)

输入格式

一个测试点共\(T\)组数据,每组数据第一行三个正整数\(n,m,k\),接下来\(k\)行,每行两个正整数\(p,q\)表示\(r_i=\frac pq\)

输出格式

每组数据输出一行,Yes代表\(n\)能够通过拆分得到\(m\)No表示不能

样例 1 输入

3
8 2 1
1 2
20 12 2
2 7
2 3
100000 1 5
1 5
2 7
5 11
4 6
1 3

样例 1 输出

No
Yes

提示

对于全部数据,满足\(1\le T\le 10, 1\le m\le n\le 10^6,k\le 20, 1\le p<q\le 100\)

样例第一组数据由8不断除以2得到

样例中第二组数据不能得到的数字是9,12,14,16,17,18,19

15可以通过20-20*2/7得到

13可以通过20*2/3得到

11可以通过15-15*2/7得到

10可以通过15*2/3得到

\(My code\)(-std c++14 -O2) pts:40/100

#include <bits/stdc++.h>
using namespace std;
bool dfs(int n, int m, int g[100][2], int k) {
	
    if (n == m) {
        return true;
    }
    if (n < m) {
        return false;
    }  
    for (int i = 0; i < k; i++) {
    	
        int p = g[i][0];
        int q = g[i][1];
        long double l = (long double)p / q; 
        int temp = n;
        n = n * l;
        temp = temp - n;
        if (dfs(n, m, g, k) || dfs(temp, m, g, k)) {
        	
            return true;
        }     
        n = temp + n;
    }  
    return false;
}
int main() {
    int sizee;
    cin >> sizee;
    for(int i=sizee;i>0;i--){
	
        int n, m, k;
        cin >> n >> m >> k;
        int g[k][2];
        for (int i = 0; i < k; i++) {
        	
            cin >> g[i][0] >> g[i][1];
        }
    	 if (dfs(n, m, g, k)) {
    	 	
            cout << "Yes" << endl;
        } else {
            cout << "No" << endl;
        }
    } 
    return 0;
}

标程

#include<bits/stdc++.h>
using namespace std;
int ci,n,m,p[25],q[25],f,k,t,v[1000010];
void dfs(int k)
{
	//cout<<k<<endl;
	
	if(v[k]) return;v[k]=1;
	if(k==0) return;
	if(f==1) return;
	if(k<m) return;
	if(k==m){
		printf("Yes\n");
		f=1;
		return;
	} 
	for(int i=1;i<=t;i++)
	{
		dfs(k*p[i]/q[i]);
		dfs(k-(k*p[i]/q[i]));//cout<<1;
	}
}
int main()
{
	cin>>ci;
	while(ci--)
	{
		//cout<<1;
		scanf("%d%d%d",&n,&m,&t);
		for(int i=1;i<=t;i++)
		{
			scanf("%d%d",&p[i],&q[i]);
		}
		f=0;
		memset(v,0,sizeof(v));
		dfs(n);
		if(f==0)
		{
			printf("No\n");
		}
	}
	return 0;
}
/*
3
8 2 1
1 2
20 12 2
2 7
2 3
100000 1 5
1 5
2 7
5 11
4 6
1 3*/

T2 哈密顿路径

题目内容

有一张\(n\times n\)的棋盘,其中\(n\)是奇数,其中有两个点不能经过,这两个点中有一个点在主对角线上,请给出一条不重不漏地经过所有能经过的点的路径。注意棋盘是四连通的,意思是路径中相邻的两个格点必须有一条公共边。

输入格式

输入一共四个整数\(n,k,x,y\)表示棋盘是\(n\times n\)的,两个不能经过的点是\((k,k),(x,y)\)。保证\(n\)是奇数。

输出格式

输出一个\(n\times n\)的矩阵,其中矩阵上的数字表示这个网格是路径中经过的第几个格子,不能被经过的点上的数字为0

样例 1 输入

3 1 2 3

样例 1 输出

0 2 1 
4 3 0 
5 6 7 

提示

测试点1,\(n\le 5\),不能经过的点为\((1,1),(2,2)\)

测试点2,\(n\le 5, k=1\)

测试点3,\(n\le 3\)

测试点4,5,\(n\le 5\)

测试点6,不能经过的点为\((1,1),(2,2)\)

测试点7,\(k=1\)

对于全部十个测试点,\(3\le n\le 99,1\le k,x,y\le n\)

标程 pts:60/100

#include<bits/stdc++.h>
using namespace std;
int n,k,x,y;
int mapp[100][100],dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int ans[100][100];
bool ansover=false;
void dfs(int x,int y,int step)
{
	if(ansover)return;
	if(step==n*n-1)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
				printf("%d ",ans[i][j]);
			printf("\n");
		}
		ansover=true;
		return;
	}
	for(int i=0;i<4;i++)
	{
		if(x+dir[i][0]>=1&&x+dir[i][0]<=n&&y+dir[i][1]>=1&&y+dir[i][1]<=n&&ans[x+dir[i][0]][y+dir[i][1]]==-1)
		{
			ans[x+dir[i][0]][y+dir[i][1]]=step;
			dfs(x+dir[i][0],y+dir[i][1],step+1);
			ans[x+dir[i][0]][y+dir[i][1]]=-1;
		}
	}
}
void quickdeal(int x,int y,int step)
{
	if(x==2&&y==1)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
				printf("%d ",ans[i][j]);
			printf("\n");
		}
		return;
	}
	if(y==1&&x>1)
	{
		if(x%2==1)
		{
			ans[x-1][y]=step;
			quickdeal(x-1,y,step+1);
			return;
		}
		else
		{
			ans[x][y+1]=step;
			quickdeal(x,y+1,step+1);
			return;
		}
	}
	if(y==2&&x>1)
	{
		if(x%2==1)
		{
			ans[x][y-1]=step;
			quickdeal(x,y-1,step+1);
			return;
		}
		else
		{
			ans[x-1][y]=step;
			quickdeal(x-1,y,step+1);
			return;
		}
	}
	if(x==n)
	{
		if(y%2==1)
		{
			ans[x][y-1]=step;
			quickdeal(x,y-1,step+1);
			return;
		}
		else
		{
			ans[x-1][y]=step;
			quickdeal(x-1,y,step+1);
			return;
		}
	}
	if(x==n-1)
	{
		if(y%2==1)
		{
			ans[x+1][y]=step;
			quickdeal(x+1,y,step+1);
			return;
		}
		else
		{
			ans[x][y-1]=step;
			quickdeal(x,y-1,step+1);
			return;
		}
	}
	if(y==n)
	{
		if(x%2==1)
		{
			ans[x+1][y]=step;
			quickdeal(x+1,y,step+1);
			return;
		}
		else
		{
			ans[x][y-1]=step;
			quickdeal(x,y-1,step+1);
			return;
		}
	}
	if(y==3)
	{
		if(x%2==1)
		{
			ans[x][y+1]=step;
			quickdeal(x,y+1,step+1);
			return;
		}
		else
		{
			ans[x+1][y]=step;
			quickdeal(x+1,y,step+1);
			return;
		}
	}
	if(x%2==1)
	{
		ans[x][y+1]=step;
		quickdeal(x,y+1,step+1);
		return;
	}
	else
	{
		ans[x][y-1]=step;
		quickdeal(x,y-1,step+1); 
		return;
	}
}
int main(){
	memset(ans,-1,sizeof(ans));
	scanf("%d%d%d%d",&n,&k,&x,&y);
	ans[x][y]=ans[k][k]=0;
	if((k==1&&x==2&&y==2)||(k==2&&x==1&&y==1))
	{
		ans[1][2]=1;
		quickdeal(1,2,2);
		return 0;
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if((i==j&&i==k)||(i==x&&j==y))continue;
			ans[i][j]=1;
			dfs(i,j,2);
			ans[i][j]=-1;
		}
	}
	return 0;
}


T3 冲

题目背景

你正在闯一个地堡,此时你的生命值,食物,魔法任意一项减到负数都会导致闯关失败。

题目内容

你正在闯一个地堡,此时你的生命值,食物,魔法任意一项减到负数都会导致闯关失败。

地堡有\(2n\)个房间,通关每一个房间都需要消耗一定的生命值,食物,魔法,同时通关了也可以帮你补充一些。
一些房间的钥匙需要通关另一个房间才能拿到,具体的,对于所有\(1\le x\le n\),进入\(x+n\)号房间的钥匙在\(x\)号房间中。

所有房间都可以使用传送门到达任意房间的入口,这个传送门是双向的,从另一边过来也消耗相同的时间。
你需要用最短的时间来通关所有房间。因此你需要规划一个合理的闯关顺序,使得传送的总时间最少。

输出最少的传送时间,如果无论如何都不能通过,则输出-1

输入格式

第一行一个整数\(n\)

第二行三个整数分别表示初始的生命,食物,魔法值。

接下来\(2n\)行,第\(i\)行有\(i-1\)个整数,第\(i\)行第\(j\)个整数表示\(i,j\)房间之间的传送门需要消耗的时间。

接下来\(2n\)行,每行\(6\)个整数,分别表示这个房间通关后补充的生命,食物,魔法值和通关这个房间需要的生命,食物,魔法值。

输出格式

一行一个整数,表示最少通关时间,如果无论如何都不能通过,则输出-1

样例 1 输入

5 9 28 

5 
9 1 
5 9 8 
6 2 8 7 
4 2 6 6 6 
9 10 3 8 6 9 
10 4 2 9 3 2 
8 3 3 3 7 8 
10 1 4 10 7 3 
3 9 6 8 6 8 
9 5 7 2 9 6 

样例 1 输出

23

提示

对于30%的数据,\(n\le 5\)

对于50%的数据,\(n\le 8\)

对于另外20%的数据,传送时间为0

对于全部数据,\(n\le 11,0\le 所有数字\le 10000\)

样例的路径通关顺序是3-2-1-6-5-4

标程

#include <bits/stdc++.h>
using namespace std;
constexpr int MAXN = 22;
constexpr int INF = 100000000;

struct Health {
    int x, y, z;
};

Health operator+(const Health& a, const Health& b) {
    return {a.x + b.x, a.y + b.y, a.z + b.z};
}

Health operator-(const Health& a, const Health& b) {
    return {a.x - b.x, a.y - b.y, a.z - b.z};
}

struct Room {
    Health gain;
    Health need;
};

int n;
int dis[MAXN][MAXN];
Room rooms[MAXN];

int mem[MAXN][1<<MAXN];

int dfs(int mask, int cur, Health health) {
    if (mask == (1<<2*n)-1) return 0;
    if (mem[cur][mask]) return mem[cur][mask]-1;
    int ans = INF;
    int iter_mask = (~mask) & ((1<<2*n)-1);
    while (iter_mask) {
        int nxt = __builtin_ctz(iter_mask);
        iter_mask ^= 1<<nxt;
        if (nxt >= n && (mask>>(nxt-n)&1) == 0) continue;
        if (health.x < rooms[nxt].need.x || health.y < rooms[nxt].need.y || health.z < rooms[nxt].need.z) continue;
        Health new_health = health - rooms[nxt].need + rooms[nxt].gain;
        int new_ans = dfs(mask|(1<<nxt), nxt, new_health) + dis[cur][nxt];
        if (new_ans < ans) ans = new_ans;
    }
    mem[cur][mask] = ans+1;
    return ans;
}

int main() {
    // memset(mem, -1, sizeof(mem));

    cin >> n;
    Health init_health;
    cin >> init_health.x >> init_health.y >> init_health.z;
    for (int i = 0; i < 2*n; ++i) {
        for (int j = 0; j < i; ++j) {
            cin >> dis[i][j];
            dis[j][i] = dis[i][j];
        }
    }
    for (int i = 0; i < 2*n; ++i) {
        cin >> rooms[i].gain.x >> rooms[i].gain.y >> rooms[i].gain.z;
        cin >> rooms[i].need.x >> rooms[i].need.y >> rooms[i].need.z;
    }

    int ans = INF;
    for (int st = 0; st < n; ++st) {
        if (init_health.x < rooms[st].need.x || init_health.y < rooms[st].need.y || init_health.z < rooms[st].need.z) continue;
        Health new_health = init_health - rooms[st].need + rooms[st].gain;
        int new_ans = dfs(1<<st, st, new_health);
        if (new_ans < ans) ans = new_ans;
    }

    if (ans >= INF) ans = -1;
    cout << ans << endl;

    return 0;
}

T4 交换

题目内容

你有一个\(m\times m\)的矩阵,一开始格点\((i,j)\)上的数字为\((i-1)\times m+j\),一共有三种共\(k\)个操作。

0 x y: 交换第\(x\)行和第\(y\)

1 x y: 交换第\(x\)列和第\(y\)

2 x_1 y_1 x_2 y_2: 交换\((x_1,y_1),(x_2,y_2)\)两格

现在给你一串指令,每个指令是对矩阵依次进行第\(l\)到第\(r\)个操作,请计算出最后的矩阵。

输入格式

第一行两个整数\(m,k\)表示矩阵大小,操作数。

接下来\(k\)行依次给出各个操作。

接下来一样一个整数\(q\)表示指令数。

接下来\(q\)行每行两个数\(l,r\)表示指令。

输出格式

输出\(m\)行,每行\(m\)个数表示矩阵。

样例 1 输入

1 3 4
0 3 1
1 3 4
0 2 4
2 4 2 4 4
5
1 4
3 5
1 3
4 5
2 4

样例 1 输出

9 10 11 12 
5 7 6 8 
1 2 3 4 
13 15 14 16 

样例 2 输入(超长警告!!!!!)

20 300
1 19 8
0 19 1
1 19 8
0 2 8
2 4 2 16 16
1 9 20
2 8 16 19 20
1 12 19
2 2 8 13 3
0 17 8
2 1 4 20 7
1 13 19
0 8 6
0 9 5
2 12 19 6 18
1 1 20
2 12 13 4 13
1 10 1
1 13 1
1 7 15
1 2 16
0 13 20
2 10 10 6 20
1 5 14
0 14 16
1 2 11
2 9 17 10 20
2 8 6 20 17
1 10 10
0 18 6
1 15 9
0 17 5
2 8 2 1 7
2 6 8 18 14
1 9 20
2 1 19 6 5
2 6 7 16 14
1 11 11
2 17 9 20 20
2 17 17 18 17
2 9 11 8 20
1 20 17
2 19 1 12 7
1 8 19
2 20 4 6 7
1 13 10
2 6 5 12 15
2 16 18 8 4
2 9 5 16 1
1 15 18
0 14 3
2 4 2 7 4
0 10 10
2 19 14 15 6
0 9 14
2 7 7 1 9
1 6 1
0 18 20
2 15 10 19 7
0 4 20
0 11 6
1 7 8
0 20 20
0 1 3
2 3 12 2 17
2 1 11 9 11
0 9 5
1 15 20
0 4 14
2 3 20 6 2
0 8 19
0 9 16
1 2 2
1 7 9
0 20 11
1 15 12
0 17 11
0 6 8
2 3 11 9 8
2 13 18 4 4
1 3 19
1 17 19
1 15 6
1 6 18
2 8 13 1 17
0 7 8
1 14 18
0 12 20
1 9 6
0 16 6
1 7 5
2 10 11 14 2
2 15 11 4 6
2 9 4 10 4
1 14 12
1 17 12
0 6 2
0 11 7
0 19 16
1 4 14
1 2 7
1 1 6
1 8 16
0 17 11
1 12 14
0 9 10
2 20 18 19 7
1 19 17
2 7 13 7 11
2 16 12 14 1
2 1 6 4 13
2 7 20 4 11
2 11 9 9 1
1 15 19
0 14 13
1 11 10
0 12 7
1 1 9
0 5 19
0 16 18
1 13 12
0 5 6
2 18 11 16 12
1 19 18
1 6 16
1 17 1
2 16 13 10 2
2 7 15 9 7
2 15 1 10 13
0 6 3
2 19 5 9 20
1 2 20
0 5 1
1 3 10
0 7 2
0 9 17
2 2 18 18 13
0 19 10
2 7 10 12 19
0 10 18
1 11 9
0 20 3
1 5 4
0 4 5
2 12 12 19 18
0 10 13
0 19 8
0 15 5
1 2 17
2 6 13 15 1
2 10 4 8 3
2 16 1 8 10
2 2 13 5 6
1 1 3
2 9 20 2 12
0 14 4
1 16 18
1 3 7
1 4 3
0 5 13
0 19 19
1 4 18
2 17 19 1 3
0 15 6
0 19 5
0 18 3
1 18 3
2 10 3 10 15
1 2 9
0 9 16
1 4 9
0 12 20
0 15 12
0 3 2
0 7 11
0 14 10
0 3 12
1 16 15
0 16 8
1 16 4
0 12 9
0 2 4
2 18 8 20 19
2 3 5 11 15
0 17 13
1 14 3
0 11 5
0 10 19
1 12 8
0 13 20
2 15 8 10 17
0 18 8
2 11 9 12 19
2 12 18 10 12
1 14 3
2 2 14 6 11
1 4 13
1 12 18
0 19 19
1 8 19
2 18 16 15 18
2 6 10 20 6
0 5 18
0 13 6
2 3 1 9 18
2 18 7 6 15
0 5 5
2 12 11 16 8
0 19 14
2 13 10 7 12
0 9 5
0 10 19
1 3 11
1 20 8
0 12 11
1 4 15
2 20 10 16 16
0 1 13
0 16 10
2 18 1 13 5
1 5 6
0 20 17
1 2 20
2 12 5 15 6
2 3 12 6 9
2 19 9 20 19
2 6 6 14 3
0 2 7
2 12 10 10 4
1 1 12
1 9 6
2 6 4 15 4
0 14 20
1 20 3
1 4 7
2 1 3 4 10
0 12 8
0 15 7
2 14 17 19 2
1 11 11
1 5 14
1 8 10
1 10 13
0 6 19
2 12 15 15 11
1 11 9
1 15 16
0 17 10
0 16 12
0 11 8
1 17 11
0 7 8
2 16 17 11 6
2 7 16 8 18
2 2 17 17 20
2 12 20 18 8
1 16 16
2 5 1 8 4
0 13 15
2 1 5 19 2
2 7 9 18 1
1 15 15
1 11 9
1 3 6
2 2 4 7 3
1 11 4
1 10 6
2 5 2 20 13
2 18 15 12 18
0 8 1
0 15 15
2 1 11 13 13
1 10 16
2 10 16 11 2
2 19 8 12 14
2 4 16 17 15
1 20 10
1 14 17
1 13 7
2 19 4 14 20
2 17 6 14 8
1 11 8
2 4 13 13 3
1 14 7
0 16 11
1 5 3
0 12 5
2 1 7 18 13
2 12 1 16 11
0 16 16
1 12 3
2 13 2 10 10
0 12 19
2 3 3 6 9
2 17 6 8 7
1 18 20
0 4 10
1 12 10
2 15 8 4 17
1 5 14
300
84 146
28 188
143 234
96 152
203 270
54 130
198 275
72 295
169 174
199 273
58 196
4 248
14 159
93 102
119 158
22 261
70 222
64 195
56 263
173 292
138 216
49 147
46 154
103 124
11 197
48 134
214 232
49 234
55 96
132 208
116 183
194 196
48 118
94 97
14 273
185 214
63 293
141 267
48 184
106 247
83 202
101 208
8 212
7 101
229 248
47 172
12 209
27 76
2 242
94 183
21 129
48 111
20 73
44 151
38 280
165 184
42 183
167 208
41 212
15 99
212 216
32 285
122 263
35 166
126 260
86 132
222 229
53 168
54 61
22 93
190 271
152 167
151 235
88 134
113 127
137 286
267 279
74 222
157 224
10 272
66 141
206 248
30 183
162 280
90 149
224 296
198 294
4 78
132 298
61 86
172 293
98 189
188 288
99 198
140 242
80 285
160 209
68 166
6 135
90 262
57 212
87 245
16 108
150 266
261 279
157 262
154 163
242 279
53 73
92 208
192 233
34 253
28 82
127 225
170 237
97 144
159 170
269 293
81 213
32 276
64 188
25 300
147 292
115 170
41 69
69 79
164 238
9 56
162 215
21 220
67 138
175 208
143 260
94 213
214 216
5 117
216 254
22 219
138 284
104 246
11 55
54 174
206 227
116 151
44 210
104 232
164 164
8 292
164 212
71 230
215 286
80 158
227 274
59 240
172 232
249 285
72 105
214 291
59 159
117 240
233 268
262 283
60 207
50 199
116 243
13 164
152 272
125 159
23 68
51 115
205 250
105 206
18 261
56 68
118 179
136 198
11 254
7 180
130 177
31 140
29 98
68 95
37 101
27 205
198 205
95 289
38 211
46 108
153 258
7 122
26 181
123 210
10 97
4 152
91 115
212 252
86 95
56 96
66 105
229 257
181 191
7 68
76 256
174 261
80 287
75 274
75 154
13 102
202 232
124 243
90 92
89 164
27 34
66 264
49 251
96 197
192 236
20 185
143 154
43 87
115 280
159 247
73 276
3 102
155 192
14 153
124 182
43 157
15 157
27 167
45 179
65 107
46 173
241 296
31 89
219 253
148 209
185 228
217 284
51 106
90 251
82 271
114 298
240 300
45 63
31 37
233 245
101 111
20 259
114 172
151 196
198 297
43 101
196 238
47 292
207 250
61 226
28 298
37 172
141 149
158 224
70 102
17 81
52 182
18 210
183 263
163 215
88 277
275 298
44 89
164 254
57 72
126 286
16 34
119 281
5 226
94 292
38 289
92 169
177 260
139 273
8 200
143 249
75 225
104 175
103 243
60 295
9 292
18 68
144 290
64 137
19 286
220 289
96 146
19 25
44 275
95 167
203 288
98 169
194 296

样例 2 输出(超长警告!!!)

369 204 209 241 35 219 17 44 383 287 26 195 345 355 78 280 186 334 81 82 
225 160 341 243 233 387 203 276 103 108 98 221 261 374 384 263 282 224 125 66 
55 264 230 114 68 123 102 298 294 30 234 2 377 307 274 8 392 400 162 297 
132 181 352 245 88 244 291 312 154 139 295 126 153 47 6 167 70 14 58 390 
137 129 100 67 72 85 237 326 133 16 397 265 164 278 199 27 110 176 62 236 
214 56 290 189 166 216 218 281 205 95 363 332 131 86 327 284 31 92 358 48 
45 222 29 169 148 267 194 343 325 202 106 193 292 180 269 333 285 57 94 173 
360 40 5 366 386 127 18 240 349 223 380 105 113 347 83 187 119 38 177 273 
73 304 367 39 28 41 200 12 348 324 330 74 179 342 381 361 250 268 3 272 
121 353 156 305 309 215 317 370 258 96 198 13 9 61 388 252 362 339 270 320 
163 185 7 249 184 319 183 1 182 135 206 21 379 172 335 321 75 365 34 49 
253 197 36 116 226 104 329 168 19 24 296 15 79 201 357 210 336 385 344 279 
351 23 288 141 77 338 231 190 211 248 299 393 256 337 97 33 165 316 208 220 
275 303 376 313 59 238 46 192 259 398 318 260 262 138 228 310 242 111 283 394 
37 346 60 52 99 157 371 136 229 331 340 359 150 93 130 90 217 145 311 140 
25 147 159 4 213 112 122 178 89 107 322 50 22 146 161 251 117 308 143 212 
11 191 51 144 84 395 246 134 314 289 120 155 171 63 271 124 43 53 293 54 
158 373 64 356 175 378 101 257 239 87 151 247 300 149 277 109 396 128 69 391 
80 32 76 286 382 42 368 235 232 301 254 188 315 152 118 364 354 115 71 350 
196 306 266 389 227 91 255 399 142 10 302 174 375 372 65 207 323 328 20 170 

提示

\(m\le 20\)

对于10%的数据,\(k,q\le 300\)

对于30%的数据,\(k\le 300\)

对于另外20%的数据,\(l=1,r=k\)

对于另外20%的数据,没有2号操作,\(k,q\le 10000\)

对于全部数据,\(k,q\le 10^5\)

标程

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

const int MAXM = 32;
const int MAXK = 100010;

int m, k, q;
int mat[MAXM][MAXM];

struct Op {
    int op, x1, y1, x2, y2;
};
Op ops[MAXK];

struct Mapping {
    short int map[MAXM*MAXM];
};

Mapping operator*(const Mapping &a, const Mapping &b) {
    Mapping c;
    for (int i = 1; i <= m * m; ++i)
        c.map[i] = b.map[a.map[i]];
    return c;
}

Mapping get_inv(const Mapping &a) {
    Mapping b;
    for (int i = 1; i <= m * m; ++i)
        b.map[a.map[i]] = i;
    return b;
}

Mapping get_1() {
    Mapping a;
    for (int i = 1; i <= m * m; ++i)
        a.map[i] = i;
    return a;
}

inline int pos2index(int x, int y) {
    return (x - 1) * m + y;
}

Mapping op2mapping(Op op) {
    Mapping res = get_1();
    if (op.op == 0) {
        for (int i = 1; i <= m; ++i)
            swap(res.map[pos2index(op.x1, i)], res.map[pos2index(op.y1, i)]);
    } else if (op.op == 1) {
        for (int i = 1; i <= m; ++i)
            swap(res.map[pos2index(i, op.x1)], res.map[pos2index(i, op.y1)]);
    } else {
        swap(res.map[pos2index(op.x1, op.y1)], res.map[pos2index(op.x2, op.y2)]);
    }
    return res;
}

Mapping mapping_inv_pp[MAXK], mapping_pp[MAXK];


int main() {
    scanf("%d %d", &m, &k);
    for (int i = 1; i <= k; ++i) {
        int op, x1, y1, x2, y2;
        scanf("%d", &op);
        scanf("%d%d", &x1, &y1);
        if (op == 2)
            scanf("%d%d", &x2, &y2);
        ops[i] = {op, x1, y1, x2, y2};
    }

    mapping_pp[0] = get_1();
    mapping_inv_pp[0] = get_1();
    for (int i = 1; i <= k; ++i) {
        Mapping cur = op2mapping(ops[i]);
        mapping_pp[i] = mapping_pp[i-1] * cur;
        mapping_inv_pp[i] = get_inv(mapping_pp[i]);
    }

    Mapping final_mapping = get_1();
    scanf("%d", &q);
    for (int i = 1; i <= q; ++i) {
        int l, r;
        scanf("%d%d", &l, &r);
        final_mapping = final_mapping * mapping_inv_pp[l-1] * mapping_pp[r];
    }

    Mapping result = get_inv(final_mapping);

    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= m; ++j)
            printf("%d ", result.map[pos2index(i, j)]);
        printf("\n");
    }

    return 0;
}
posted @ 2023-08-01 19:40  _Unnamed  阅读(61)  评论(0)    收藏  举报