The shuffle Problem
Description
Any case of shuffling of n cards can be described with a permutation of 1 to n. Thus there are totally n! cases of shuffling. Now suppose there are 5 cards, and a case of shuffle is <5, 3, 2, 1, 4>, then the shuffle will be:
Before shuffling:1, 2, 3, 4, 5
The 1st shuffle:5, 3, 2, 1, 4
The 2nd shuffle:4, 2, 3, 5, 1
The 3rd shuffle:1, 3, 2, 4, 5
The 4th shuffle:5, 2, 3, 1, 4
The 5th shuffle:4, 3, 2, 5, 1
The 6th shuffle:1, 2, 3, 4, 5(the same as it is in the beginning)
You’ll find that after six shuffles, the cards’ order returns the beginning. In fact, there is always a number m for any case of shuffling that the cards’ order returns the beginning after m shuffles. Now your task is to find the shuffle with the largest m. If there is not only one, sort out the one with the smallest order.
Input
The first line of the input is an integer T which indicates the number of test cases. Each test case occupies a line, contains an integer n (1 ≤ n ≤ 100).
Output
Each test case takes a line, with an integer m in the head, following the case of shuffling.
Sample Input
2
1
5
Sample Output
1 1
6 2 1 4 5 3
这道题,大概就是给你n,然后让你构造出整个序列的最大循环节长度。
对整个序列,我们可以将他们划分为若干个序列,n1, n2, n3,那么整个序列的循环节长度就是所有lcm(n1, n2, n3…)(显然)
由于求lcm,如果我们每次都用同样的n1, n1, n1,lcm是最小的,因此排除这种情况,这就是进行dfs搜索的前提。
边搜索的时候,边计算lcm,剪枝。
网上有dp预处理最大lcm的方法,看了好多,抄的一模一样不想吐槽了。
这道题对我加深循环群的理解还是挺有帮助的。。
trick还是比较多,注意字典序输出,注意无贡献的ni要拆成1
代码如下:
//
// Created by Running Photon on 2015-09-17
// Copyright (c) 2015 Running Photon. All rights reserved.
//
//
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;
inline int read() {
char c = getchar();
int f = 1;
while(!isdigit(c)) {
if(c == '-') f = -1;
c = getchar();
}
int x = 0;
while(isdigit(c)) {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
int t, n;
ll big = 0;
int top;
int cir[maxv];
int tmp[maxv];
ll lcm(ll a, ll b) {
return a / __gcd(a, b) * b;
}
void dfs(int id, int res, int from, ll l) {
if(!res) {
// ll l = 1;
// for(int i = 0; i < id; i++) {
// l = lcm(l, tmp[i]);
// }
if(big < l) {
big = l;
for(int i = 0; i < id; i++)
cir[i] = tmp[i];
top = id;
}
return;
}
if(res <= from) {
tmp[id] = res;
ll temp = l;
l = lcm(l, res);
dfs(id + 1, 0, from, l);
l = temp;
}
else {
for(int i = from; i <= res; i++) {
tmp[id] = i;
ll temp = l;
l = lcm(l, i);
dfs(id + 1, res - i, i + 1, l);
l = temp;
}
}
}
int ans[maxv];
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
scanf("%d", &t);
while(t--) {
big = 0;
top = 0;
scanf("%d", &n);
if(n == 1) {puts("1 1"); continue;}
dfs(0, n, 1, 1);
for(int i = 1; i <= n; i++)
ans[i] = i;
int id = 1;
sort(cir, cir + top);
vector <int> v;
for(int i = 0; i < top; i++) {
int flag = 0;
for(int j = i + 1; j < top; j++) {
if(cir[j] % cir[i] == 0) flag = 1;
}
if(flag) while(cir[i]--) v.push_back(1);
else v.push_back(cir[i]);
}
sort(ALL(v));
for(int i = 0; i < v.size(); i++) {
for(int j = id; j < v[i] + id - 1; j++) {
swap(ans[j], ans[j+1]);
}
id += v[i];
}
// for(int i = 0; i < v.size(); i++)
// printf("%d ", v[i]);
// puts("");
printf("%I64d", big);
for(int i = 1; i <= n; i++)
printf(" %d", ans[i]);
puts("");
}
return 0;
}