codeforces 1474 E

题目链接:https://codeforces.com/contest/1474/problem/E

开始以为答案是 (1^2 + 2 ^ 2 + ... + (n - 1) ^ 2)
看题解以后发现没有这么简单。。

因为每次交换必定会让一个位置还原,所以每个位置都要尽量和当前没有还原位置中的最远的位置交换,
也就是把首位两个位置放到最后再还原
最后的贡献为 $$(n-1)^2 + 2 * (n-2) ^ 2 + ... + t * 1 ^ 2$$
其中 (t) 根据 (n) 的奇偶性决定

构造方案就按照交换顺序反向构造即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;

#define mp make_pair

const int maxn = 100010;

int T, n;
int a[maxn], to[maxn];
ll ans = 0;
vector<P> pa;

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	T = read();
	while(T--){
		pa.clear();
		ans = 0;
		n = read();
		int cnt = n - 1, delta = 2;
		for(int i = 1 ; i <= n ; ++i) a[i] = i;
		--cnt; swap(a[1], a[n]);
		pa.push_back(mp(1, n));
		
		while(cnt){
			--cnt;
			swap(a[1], a[n - delta + 1]);
			pa.push_back(mp(n - delta + 1, 1));
			
			if(cnt){
				--cnt;
				swap(a[n], a[delta]);
				pa.push_back(mp(delta, n));
			}
			++delta;
		}

		ans = 1ll * (n - 1) * (n - 1); 
		int tot = n - 2;
		cnt = n - 2; 
		while(cnt){
			--cnt;
			ans += 1ll * tot * tot;
			if(cnt){
				--cnt;
				ans += 1ll * tot * tot;
			}
			--tot;
		}

		printf("%lld
", ans);
		for(int i = 1 ; i <= n ; ++i) printf("%d ", a[i]); printf("
");
		printf("%d
", n - 1);
		
		reverse(pa.begin(), pa.end());
		
		for(auto p: pa){
			printf("%d %d
", p.first, p.second);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/14331975.html