AcWing 108. 奇数码问题

题目

思考

看了很久才发现有一个很大的错误观点:空格不代表任何数,既非0也非9。
因为这个问题调了很久。

看到奇数码游戏这个话题,我们就先把它转换为还原问题

那么我们空开空格这个问题,也就是要把剩下的数都排成\(1,2,3...,n^2-1\)

进一步说,如果有\(A,B\)两个局面,且这两个局面都能还原,那么这两个局面一定可以相互转换。
也就是:A --> 还原 --> B。

当然,奇数码游戏是一定存在无法还原的情况的,但是却又有:A --> C --> B。
既然都能转化到同一局面,那么一定存在通性(A,B之间)。

推导

每次交换都会改变数字的顺序,那么不妨把二维的平面展开变成\(n^2 - 1\)个元素的序列(前面说过除去空格),然后观察该序列的逆序对的改变情况。

这里以\(n = 3\)为例:

1 2 3
4 5 6   ->  1 2 3 | 4 5 6 | 7 8 X 转换后
7 8 X

请注意,空格不包含在元素中,请忽略空格的任何意义。

左右变换,发现序列的逆序对数并没有发生改变

1 2 3 | 4 5 6 | 7 8 X
1 2 3 | 4 5 6 | 7 X 8
上下变换,会发现有序列中6,7,8之间的逆序对关系发生了改变
那么我们假设有a1,a2,a3有如上关系;

如果a1和a2,a3是逆序对,那么交换后,逆序对数量减少2;
如果a1和a2,a3不是逆序对,那么交换后,逆序对数量增加2;
如果a1和a2,a3中的一个是逆序对,那么交换后,逆序对的数量不变。
依次类推,如果有n个数,那么一定有n-1个数会改变,且每个数的改变值都是正负1,那么无论n取何值,改变量都是偶数。

1 2 3 | 4 5 6 | 7 8 X
1 2 3 | 4 5 X | 7 8 6

总结一下,就是左右互换逆序对数量不变,上下互换逆序对数量改变的值为偶数,也就是说,无论如何改变,展开后序列的逆序对数的奇偶性永远不发生变化

问题迎刃而解,用归并排序求逆序对,在验证两式的奇偶性是否相同。

100 pts

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 250010;
int n;
int temp[N], top;

ll msort(int l, int r, int *a)
{
	if(l >= r) return 0;
    
	int mid = l + r >> 1;
	ll res = msort(l, mid, a) + msort(mid + 1, r, a);
	
	top = 0;
	int i = l, j = mid + 1;
	while(i <= mid && j <= r)
		if(a[i] <= a[j]) temp[top ++ ] = a[i ++ ];
		else temp[top ++ ] = a[j ++ ], res += (ll)(mid - i + 1);
	while(i <= mid) temp[top ++ ] = a[i ++ ];
	while(j <= r) temp[top ++ ] = a[j ++ ];
	for(i = l, j = 0; i <= r; i ++ , j ++ ) a[i] = temp[j];
	return res;
}

int a[N], p[N];
int main()
{
	//freopen("C.in", "r", stdin);
	//freopen("C.out", "w", stdout);
	
	while(cin >> n)
	{
		n *= n;
		bool space = false;
		for(int i = 1; i <= n; i ++ )
		{
			int x; cin >> x;
			if(!x) space = true;
			else a[i - space] = x;
		}
		
		space = false;
		for(int i = 1; i <= n; i ++ )
		{
			int x; cin >> x;
			if(!x) space = true;
			else p[i - space] = x;
		}
		
		ll res1 = msort(1, n - 1, a);
		ll res2 = msort(1, n - 1, p);
        //cout << res1 << ' ' << res2 << endl;
		
		if((res1 & 1) == (res2 & 1)) puts("TAK");
		else puts("NIE");
	}
	
	return 0;
}
posted @ 2023-01-29 20:55  Sankano  阅读(57)  评论(0编辑  收藏  举报