Rayan Programming Contest 2024 - Selection (Codeforces Round 989, Div. 1 + Div. 2)題解記錄(A~E)

长皆發表於2024-12-05

比賽連結:https://codeforces.com/contest/2034
本場不是賽時也不是vp的,單純賽後補的,現在看來怎麼感覺比上次的edudiv2更簡單些?

A. King Keykhosrow's Mystery

題面:
有一個關於睿智的國王 Keykhosrow 的故事,他擁有一個宏偉的寶庫,裡面裝滿了來自波斯帝國各地的寶藏。然而,為了防止盜竊和確保他的財富安全,Keykhosrow 國王的金庫被一把神奇的鎖封住了,只有解開謎題才能開啟。
這個謎題涉及到兩個神聖的數字 \(a\)\(b\)。要開啟金庫,挑戰者必須確定滿足兩個條件的最小金鑰數字 \(m\)

  • \(m\) 必須大於或等於 \(a\)\(b\) 中的至少一個。
  • \(m\)\(a\) 除時的餘數必須等於 \(m\)\(b\) 除時的餘數。

只有找到 \(m\) 的最小正確值,才能開啟金庫並獲得傳說中的寶藏!
輸入:
第一行包含一個整數 \(t\) $ (1 \leq t \leq 100) $,表示測試用例的數量。

每個測試用例由一行組成,包含兩個整數 \(a\)\(b\) $ (1 \leq a, b \leq 1000) $
輸出:
對於每個測試用例,列印滿足上述條件的最小整數 \(m\)
樣例:
2
4 6
472 896


12
52864
思路:
做法一:顯然\(1000*1000*100\)的時間複雜度時可以暴力列舉檢驗的,但是這裡用long long會TLE,用int就不會TLE了。
做法二:直接求lcm,最小公倍數。因為\(m=a*k1+c\)\(m=b*k2+c\),兩者連立,發現\(a*k1=b*k2\),顯然他們兩個得最小公倍數就為答案

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                    long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
	ll a,b;
	cin>>a>>b;
	ll u=gcd(a,b);
	cout<<a/u*b<<endl;
	}
	return 0;
}

B. Rakhsh's Revival

題面:
Rostam的忠實馬 Rakhsh的日子好過。曾經強大而快速的 Rakhsh 隨著時間的推移變得越來越虛弱,甚至難以移動。Rostam 擔心,如果 Rakhsh 身體的太多部位同時失去力量,Rakhsh 可能會完全停止。為了讓他的同伴繼續前進,Rostam 決定一點一點地加強 Rakhsh,這樣他身體的任何部分都不會太脆弱太久。

將 Rakhsh 的身體想象成一行點,由長度為 \(n\) 的二進位制字串 \(s\) 表示,其中每個 \(0\) 表示一個弱點,每個 \(1\) 表示一個強點。Rostam 的目標是確保沒有連續 \(m\) 點的區間是完全弱的(全部是 \(0\))。

幸運的是,Rostam 有一種叫做 Timar 的特殊能力,是他出生時從他的母親 Rudabeh 那裡繼承的。使用 Timar,他可以選擇任何長度 \(k\) 的段並立即加強所有段(將該段中的每個字元更改為 \(1\))。挑戰在於弄清楚 Rostam 需要使用 Timar 來保持 Rakhsh 移動的最少次數,確保沒有連續的完全薄弱的長度 \(m\) 點。
輸入:
第一行包含一個整數 \(t\) (\(1 \leq t \leq 10^4\)),即測試用例的數量。

每個測試用例的第一行包含三個數字 \(n\), \(m\), \(k\) (\(1 \leq m, k \leq n \leq 2 \cdot 10^5\))。每個測試用例的第二行都包含一個二進位制字串 \(s\)\(n\) 個字元 \(s_1s_2\ldots s_n\) 組成。(\(s_i \in \{0,1\}\) 對於 \(1 \leq i \leq n\))。

保證所有測試用例的 \(n\) 的總和不超過 \(2 \cdot 10^5\)
輸出:
對於每個測試用例,輸出 Rostam 需要使用 Timar 保持 Rakhsh 移動的最小次數,確保沒有長度為 \(m\) 的連續完全弱點。
樣例:
3
5 1 1
10101
5 2 1
10101
6 3 2
000000
———————
2
0
1
思路:最優方法應該是你在不符合的情況下放一個塊使之符合答案,所以統計區間段,一旦區間段不符合,就以這個為左端點設定加強段

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                   long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}

int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		ll n,m,k;
		cin>>n>>m>>k;
		string f;
		cin>>f;
		ll cnt=0;
		ll ans=0;
		ll dx=0;
		for(ll i=0;i<f.size();i++)
		{
			if(f[i]=='0'&&dx==0)
			{
				cnt++;
			}
			if(cnt==m)
			{
				cnt=0;
				dx=k;
				ans++;
			}
			if(f[i]=='1')
			cnt=0;
			dx--;
			dx=max(dx,(ll)0);
		}
		cout<<ans<<endl;
	}
	return 0;
}

C. Trapped in the Witch's Labyrinth

題面:
在 Rostam的第四個任務 中,來自 Shahnameh 的傳奇英雄,一位老巫婆創造了一個魔法迷宮來困住他。迷宮是一個由 \(n\) 行和 \(m\) 列組成的矩形網格。迷宮中的每個單元格都指向一個特定的方向:上、下、左或右。巫婆施法讓 Rostam 每當他處於一個單元格時,他將移動到由該單元格指示的下一個單元格。

如果 Rostam 最終走出迷宮,他將從巫婆的咒語中解脫出來並擊敗她。然而,如果他永遠被困在迷宮中,他將永遠無法逃脫。

巫婆還沒有確定所有單元格的方向。她想要以一種方式分配方向給未指定的單元格,使得 Rostam 將永遠被困住的起始單元格數量最大化。您的任務是找出使 Rostam 被困的起始單元格的最大數量。
輸入:
第一行的輸入包含一個整數 \(t\) (\(1 \leq t \leq 10^4\)),表示測試用例的數量。

對於每個測試用例:

  • 第一行包含兩個整數 \(n\)\(m\) (\(1 \leq n, m \leq 1000\)),代表迷宮中的行數和列數。
  • 接下來的 \(n\) 行,每行包含一個由 \(m\) 個字元組成的字串,表示迷宮中的方向。每個字元是以下之一:
    • U (上)
    • D (下)
    • L (左)
    • R (右)
    • ? (未指定的方向)

保證所有測試用例的 \(n \cdot m\) 的總和不超過 \(10^6\)
輸出:
對於每個測試用例,列印一個整數,這是在為未指定的單元格分配方向後,Rostam將永遠被困住的最大起始單元格數量。
樣例:
3
3 3
UUU
L?R
DDD
2 3
???
???
3 3
?U?
R?L
RDL
————
0
6
5
思路:思考不合法方案。對於外圍一圈,如果箭頭只想外面必定不符合,所以寫個dfs對於這些不符合的點進行深搜,這個深搜每次去看周圍有沒有指向自己的箭頭,有就繼續搜並打上標記。如何解決?,可以發現對於每個不合法的點可以對於他四周進行次數標記,如果一個?被打過4次標記,他就什麼方向都不行,也就是不合法點。所以最後遍歷一遍,對於?統計沒標記過四次的,對於箭頭統計沒記過的

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                   long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
string f[2500];
bool vis[1005][1005];
ll fk[1005][1005];
ll u[5]={0,0,1,0,-1};
ll d[5]={0,1,0,-1,0};
char g[5]={'0','L','U','R','D'};
ll n,m;
void dfs(ll x,ll y)
{
	vis[x][y]=1;
	for(ll i=1;i<=4;i++)
	{
		ll nx=x+u[i];
		ll ny=y+d[i];
		fk[nx][ny]++;
		if(vis[nx][ny]||nx<1||ny<1||nx>n||ny>m||g[i]!=f[nx][ny])
		continue;
		dfs(nx,ny);
	}
}
bool vi[10005][1005];
ll ck(ll x,ll y)
{
	if(vi[x][y])return 0;
	vi[x][y]=1;
	if(f[x][y]=='?')
	{
		for(ll i=1;i<=4;i++)
		{
			ll nx=x+u[i];
			ll ny=y+d[i];
			if(nx<1||ny<1||nx>n||ny>m)
			fk[x][y]++;
		}
	}
	if(f[x][y]=='U')
	{
		if(x-1<1)
		return 1;
	}
	if(f[x][y]=='D')
	{
	if(x+1>n)
	return 1;
	}
	if(f[x][y]=='R'&&y+1>m)
	return 1;
	if(f[x][y]=='L'&&y-1<1)
	return 1;

	return 0;
}
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		for(ll i=1;i<=n;i++)
		{
			cin>>f[i];
			f[i]='0'+f[i];
		}
		for(ll i=0;i<=n;i++)
		{
			for(ll j=0;j<=m;j++)vis[i][j]=fk[i][j]=vi[i][j]=0;
		}
		for(ll j=2;j<=m-1;j++)
		{
			fk[1][j]++;
			if(f[1][j]=='U')
			{
				dfs(1,j);
			}
		}
		//fk[1][1]+=2,fk[1][m]+=2;
		if(ck(1,1))dfs(1,1);
	  //  cout<<fk[1][1]<<endl;
		if(ck(1,m))dfs(1,m);
		for(ll j=2;j<=n-1;j++)
		{
			fk[j][m]++;
			if(f[j][m]=='R')
			dfs(j,m);
		}
	//	fk[n][m]+=2;
		if(ck(n,m))dfs(n,m);
		for(ll j=2;j<=m-1;j++)
		{
			fk[n][j]++;
			if(f[n][j]=='D')
			dfs(n,j);
		}
		//fk[n][1]+=2;
		if(ck(n,1))dfs(n,1);
		for(ll j=2;j<=n-1;j++)
		{
			fk[j][1]++;
			if(f[j][1]=='L')
			dfs(j,1);
		}
		ll ans=0;
		for(ll i=1;i<=n;i++)
		{
			for(ll j=1;j<=m;j++)
			{
				if(vis[i][j])continue;
				if(f[i][j]=='?'&&fk[i][j]<4)ans++;
				if(f[i][j]!='?')ans++;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

D. Darius' Wisdom

題面:
大流士 Darius 正在建造 \(n\) 座石柱,每座石柱由一個底座和頂部的 \(0\)\(1\)\(2\) 個銘文組成。

在每一步中,Darius 可以選擇兩座石柱 \(u\)\(v\),使得這兩座石柱上的銘文數量相差正好是 \(1\),並從銘文數量較多的石柱上轉移一個銘文到另一座石柱上。保證至少有一座石柱上恰好有 \(1\) 個銘文。
由於美觀是歷史建築的主要支柱,Darius 希望石柱的高度按銘文數量的非遞減順序排列。為了避免過度勞工人們的努力,他請求你計劃一個最多 \(n\) 步的序列,以根據銘文的數量將石柱排列成非遞減順序。不要求 最小化移動次數。
輸入:
第一行包含一個整數 \(t\) — 測試用例的數量。(\(1 \leq t \leq 3000\))

每個測試用例的第一行包含一個整數 \(n\) — 石柱的數量。(\(1 \leq n \leq 2 \cdot 10^5\))

第二行包含 \(n\) 個整數 \(a_1, a_2, \ldots, a_n\),其中 \(a_i \in \{0,1,2\}\) 表示第 \(i\) 列初始的銘文數量。保證至少有一列恰好有 \(1\) 個銘文。

保證所有測試用例的 \(n\) 的總和不超過 \(2 \cdot 10^5\)
輸出:

對於每個測試用例,輸出一個整數 \(k\) — 用於對列進行排序的移動次數。(\(0 \leq k \leq n\))

然後,輸出 \(k\) 行,每行包含兩個整數 \(u_i\)\(v_i\) (\(1 \leq u_i, v_i \leq n\)),代表第 \(i\) 次移動中涉及的列的索引。在每次移動中,必須滿足 \(|a_{u_i} - a_{v_i}| = 1\),並且一個銘文從銘文數量較多的列轉移到另一列。

可以證明,在給定的約束條件下,總存在一個有效的解決方案。
樣例:
3
4
0 2 0 1
3
1 2 0
6
0 1 1 2 2 2
————————————
2
2 4
2 3
2
3 1
2 3
0
思路:這題的程式碼量比上題少多了,先統計0,1的數量,然後開三個set,分別儲存0,1,2的位置,從前往後遍歷,
如果這個位置得是0,但是是1,那就把最遠得0和現在得1交換位置。順便更新下set容器,如果是2,就先把此時的2和最遠的1交換,然後再把現在的1和最遠的0交換。
如果這個位置得是1,但是是2,那就把最遠的1和現在的2交換下位置。
如果這個位置得是2時,早以解決,直接break

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
//#include<bits/stdc++.h>
#include <unordered_map>
#define ll                               long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
// const ll p=rnd()%mod;
const ll maxn=2e5+15;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
ll a[250000];
ll b[5];
set<ll>q[4];
vector<pair<ll,ll>>g;
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		ll n;
		cin>>n;
		g.clear();
		q[1].clear();
		q[2].clear();
		q[0].clear();
		b[0]=b[1]=b[2]=0;
		for(ll i=1;i<=n;i++)
		{
		cin>>a[i];
		b[a[i]]++;
		if(a[i]==1)
		q[1].insert(i);
		else if(a[i]==2)
		q[2].insert(i);
		else q[0].insert(i);
		}
		for(ll i=1;i<=n;i++)
		{
			if(b[0]>0)
			{
				if(a[i]==0)b[0]--;
				else if(a[i]==1)
				{
					auto u=q[0].rbegin();
					q[0].insert(i);
					q[1].erase(i);
					q[1].insert(*u);
					swap(a[*u],a[i]);
					g.push_back({i,*u});
						q[0].erase(*u);
					b[0]--;
				}
				else 
				{
					auto u=q[1].rbegin();
						swap(a[*u],a[i]);
					g.push_back({i,*u});
					q[2].insert(*u);
					q[1].erase(*u);
					q[1].insert(i);
					q[2].erase(i);
					 u=q[0].rbegin();
					 	swap(a[*u],a[i]);
					g.push_back({i,*u});
					q[0].insert(i);
					q[1].erase(i);
					q[1].insert(*u);
					q[0].erase(*u);
					b[0]--;
				}
			}
			else if(b[1]>0)
			{
				if(a[i]==1)b[1]--;
				else 
				{
					auto u=q[1].rbegin();
					q[2].insert(*u);
					q[1].insert(i);
					q[2].erase(i);
					swap(a[*u],a[i]);
					g.push_back({i,*u});
					b[1]--;
					q[1].erase(*u);
				}
			}
			else break;
		}
		cout<<g.size()<<endl;
		for(auto x:g)
		{
			cout<<x.first<<" "<<x.second<<endl;
		}
	}
}

E. Permutations Harmony

題面:
Rayan 想向 Reyhaneh 贈送一份禮物,以贏得她的心。但是,Reyhaneh 很特別,並且只接受一組 \(k\) 諧波排列。

我們定義一個 \(k\) 諧波排列集合為一組 \(k\)兩兩不同的排列 \(p_1, p_2, \ldots, p_k\),它們的大小為 \(n\),使得對於每一對索引 \(i\)\(j\)(其中 \(1 \leq i, j \leq n\)),以下條件成立:

\[p_1[i] + p_2[i] + \ldots + p_k[i] = p_1[j] + p_2[j] + \ldots + p_k[j] \]

您的任務是幫助 Rayan,要麼為給定的 \(n\)\(k\) 提供一個有效的 \(k\) 諧波排列集合,要麼確定這樣的集合不存在。

我們稱長度為 \(n\) 的序列為排列,如果它恰好包含從 \(1\)\(n\) 的每個整數一次。
輸入:

第一行包含一個整數 \(t\) (\(1 \leq t \leq 1000\)),表示測試用例的數量。

每個測試用例由兩個整數 \(n\)\(k\) 組成 (\(1 \leq n, k \leq 10^5\))。所有測試用例中 \(n \cdot k\) 的總和不超過 \(5 \cdot 10^5\)
輸出:

對於每個測試用例,如果存在一個 \(k\) 諧波排列集合,首先在第一行列印 "YES"。然後,列印 \(k\) 行,每行包含一個從 \(1\)\(n\) 的整數的不同排列。

如果不存在這樣的集合,請在第一行列印 "NO"。

在任何情況下,您都可以輸出 “YES” 和 “NO”(例如,字串 “yEs”、“yes” 和 “Yes” 將被識別為肯定響應)。

如果有多個答案,您可以輸出其中任何一個。
樣例:
4
3 3
4 2
5 1
3 2


YES
1 2 3
2 3 1
3 1 2
YES
1 2 3 4
4 3 2 1
NO
YES
1 2 3
3 2 1
思路:首先特判k=1時的情況。然後發現一個n序列的最多不同排序數為n!,如果k大於這個直接NO。
其實一個排列和另一個排列每列加起來等於n+1具有對稱性,如:1 2 3 ,3 2 1,他們各佔n!/2,如果k等於偶數,直接使用next_permutation(),全排列函式直接輸出此時序列和對稱序列,不要怕會重複,再重複之前,一定可以輸出完答案的,到時候break就行了
如果k為奇數,首先得考慮\(((1+n)*n/2*3)\)%\(n\)得等於0,因為如果這個不滿足就一定不能構造出,如果這個滿足了,我就只要先構造出三個符合條件的排列(這個可以看我程式碼,但是可以手畫下,可以發現只有n為奇數時此時才有解),然後剩下的利用對稱性就好了,要注意構造出的那三,相當於減少了全排列6種情況,記得再討論下此時有沒解。隨後利用hash+map去記錄前三個排列的hash值,然後使用next_permutation先檢驗此時排列和對稱排列的hash值有沒重複就好了,一個都沒重複才算合理輸出。

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
//#include<bits/stdc++.h>
#include <unordered_map>
#define ll                               long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9+7;
const ll p=rnd()%mod;
const ll maxn=2e5+15;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
bool vis[250000];
ll a[250000];
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		ll n,k;
		cin>>n>>k;
		for(ll i=1;i<=n;i++)
		{
			a[i]=i;
		}
		if(n==1&&k==1)
		{
			cout<<"YES"<<endl;
			cout<<1<<endl;
			continue;
		}
		if(k==1)
		{
			cout<<"NO"<<endl;
			continue;
		}
		ll cnt=1;
		ll pd=0;
		for(ll j=1;j<=n;j++)
		{
			cnt*=j;
			if(cnt>=k)
			{
				pd=1;
				break;
			}
		}
		if(pd==0)
		{
			cout<<"NO"<<endl;
			continue;
		}
		if(k%2==0)
		{
			cout<<"YES"<<endl;
			do
			{
				k-=2;
				for(ll i=1;i<=n;i++)
				cout<<a[i]<<" ";
				cout<<endl;
				for(ll i=1;i<=n;i++)
				cout<<n+1-a[i]<<" ";
				cout<<endl;
				if(k==0)
				break;
			} while (next_permutation(a+1,a+1+n));
		}
		else 
		{
			ll d=1;
			ll pd=0;
			for(ll i=1;i<=n;i++)
			{
				d*=i;
				if(d-6>=k-3)
				pd=1;
			}
			if(pd==0)
			{
				cout<<"NO"<<endl;
				continue;
			}
			ll u=(1+n)*n/2*3;
			map<ll,bool>mp;
			if(u%n==0)
			{
				cout<<"YES"<<endl;
				ll ha=0;
				for(ll i=1;i<=n;i++)
				{
					cout<<i<<" ";
					ha=((ha*p)%mod+i)%mod;
				}
				cout<<endl;
				mp[ha]=1;
				ha=0;
				for(ll i=(n+1)/2;i<=n;i++)
				{
					cout<<i<<" ";
					ha=((ha*p)%mod+i)%mod;
				}
				for(ll i=1;i<=(n+1)/2-1;i++)
				{
					cout<<i<<" ";
					ha=((ha*p)%mod+i)%mod;
				}
				cout<<endl;
				mp[ha]=1;
				ha=0;
				for(ll i=n;i>=1;i-=2)
				cout<<i<<" ",ha=((ha*p)%mod+i)%mod;
				for(ll i=n-1;i>=1;i-=2)
				cout<<i<<" ",ha=((ha*p)%mod+i)%mod;
				mp[ha]=1;
				cout<<endl;
				k-=3;
				if(k>0)
				{
				do
				{
					ll ha1=0,ha2=0;
					for(ll i=1;i<=n;i++)
					ha1=(ha1*p%mod+a[i])%mod;
					for(ll i=1;i<=n;i++)
					ha2=(ha2*p%mod+n+1-a[i])%mod;
					if(mp[ha1]==0&&mp[ha2]==0)
					{
						k-=2;
						for(ll i=1;i<=n;i++)
						cout<<a[i]<<" ";
						cout<<endl;
						for(ll i=1;i<=n;i++)
						cout<<n+1-a[i]<<" ";
						cout<<endl;
					}
					if(k==0)
					break;
				} while (next_permutation(a+1,a+1+n));
				}
			}
			else 
			cout<<"NO"<<endl;
		}
	}
}

相關文章