E. Permutation Shift
本题的题意是:你有种操作是让排列(原排列为1,2,3....n)循环,你循环k次则原来的排列变为a[(i-k+n)%n],例如k=2,就变成了n-1,n,1,2,3,....n-2。现在问你,
给你一个排列b[n],让你找出从(1,2,3,...n)有多少种k,以及循环k次后最多可以任意交换两个数m次,使得这个排列变为b[n]。
首先我们先找出b[n]中每一个数对应的循环多少次vis[(i-a[i]+m)%n],然后枚举每一种k的可能,因为m最多是n/3,所以最多枚举出3个不同的k,
(如果一个k是满足条件的,那么至少vis[i]得大于n/3吧,不然的话就算m等于n/3那么也不可能使得全部数到该到的位置上),然后是判断这个k是否合法,这有一个定理,
一个排列变成另一个排列是他们对应的(a[i],b[i])连边形成的联通块的个数cnt,然后需要的交换次数就是n-cnt;
#include <algorithm>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <unordered_map>
#include <vector>
#define ll long long int
#define ms(a, b) memset(a, b, sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define ull unsigned long long
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define endl "\n"
#define bug printf("-----------bug---------");
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
using namespace std;
const int maxn = 3e5 + 10;
const int maxm = 6e2 + 50;
const double eps = 1e-8;
const ll inf = 0x3f3f3f3f;
const ll lnf = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1);
const ll mod = 1e9 + 7;
int n, m;
int vis[maxn];
int a[maxn], b[maxn];
vector<int> v;
int fa[maxn];
int cnt;
int find1(int x)
{
return fa[x] == x ? x : fa[x] = find1(fa[x]);
}
bool chekc(int x)
{
for (int i = 1; i <= n;i++)
{
fa[i] = i;
}
for (int i = 1; i <= n;i++)
{
b[i] = (i - 1 - x + n) % n + 1;
}
int cnt = 0;
for (int i = 1; i <= n;i++)
{
int dx = find1(a[i]);
int dy = find1(b[i]);
if(dx==dy)
{
cnt++;
continue;
}
fa[a[i]] = b[i];
}
return n - cnt <= m;
}
void sove()
{
v.clear();
cin >> n >> m;
for (int i = 1; i <= n;i++)
{
vis[i] = 0;
}
for (int i = 1; i <= n;i++)
{
cin >> a[i];
vis[(i - a[i] + n) % n]++;
}
for (int i = 0; i < n;i++)
{
if(vis[i]<n/3)
continue;
else
{
if(chekc(i))
{
v.push_back(i);
}
}
}
cout << (int)v.size();
for(auto u:v)
{
cout << " " << u;
}
cout << endl;
}
int main()
{
IOS;
int T;
cin >> T;
while(T--)
{
sove();
}
return 0;
}