题目



解析

很神奇的一道题

显然,对于一种排列,相当于给出了数字 \(1..n\) 的对应关系,且不重复不遗漏,刚好把 \(1\) 到 \(n\) 又包含了一遍。

对,连边!

每个数向它对应的数连边,这样我们就得到了一幅图,且这幅图很有特点——全是简单环。

因为每个数的对应有且仅有一个,且不重复不遗漏,所以不存在大环套小环的情况,不存在复杂图形,而且,由于连了边,每个点是什么数字已经没有意义了。

显然,对于一个排列,最大的秩就是所有环大小的最小公倍数。

把 \(n\) 拆成几个正整数的和(正整数可以为 \(1\)),这些正整数的最小公倍数就是我们要的最大的秩,而字典序最小的拆法就是我们要输出的东西。

既然我们已经知道答案就是某个最小公倍数,那我们为什么不直接构造这个最小公倍数?

最小公倍数归根到底是很多质数的乘积,因此我们直接用质数来构造。

假设现在有三个质数 \(p_1、p_2、p_3\),它们的和 \(\leq n\),那么 \(p_1*p_2*p_3\) 一定是一个合法的答案。我们可以先弄一个大小为 \(p_1\) 的环,然后弄一个大小为 \(p_2\) 的环,再弄大小为 \(p_3\) 的环,如果n还有剩余,那么剩下的通通自环,这样一定是合法的。

推广:现在把三个质数变成 \(p1^{c1}、p2^{c2}、p3^{c3}\),他们乘起来依然是合法的。跟上面其实是一样的道理。

再推广:设环的大小为 \(w\),那么 \(w\) 可不可以包含两种或以上素数?可以,但是完全可以转化成上面的情况处理。设 \(w=p1^{c1} * p2^{c2} * p3^{c3}\),它对最小公倍数的贡献就是 \(w\),但是如果我把它拆成三个环来处理,使得每个环大小仅包含一种质数,效果是一样的。而且拆了之后,环的大小也变小了,显然答案的排列会更优。

因为我们的构造方式是:对于一个大小为 \(k\) 的环,我们先输出 \(k - 1\) 个顺序为 \(l+1..l+k-1\) 的数,然后再输 \(l\)。其中 \(l\) 为当前可填的最小的数

问题再次转化

现在问题变成:

现在有一堆质数(\(n\) 以内),每个质数的使用次数上限是已知的(就是上面的 \(c\) 的大小上限)。我要选择一些质数(或它的幂),使他们的和 \(\leq n\),然后这些质数(或它的幂)的乘积要最大。

而这其实就是有限背包问题。

设 \(f_{i,j}\) 表示我们处理到第i个质数、当前和为j所能获得的最大秩。则 \(f_{i,j}=\max(f_{i-1,j-w}*w)\)。而我们要求排列的话,只需记录一下每个状态是由哪个状态转移过来的,最后还原即可。

于是我们似乎做完了

嗯,确实是似乎

因为你会发现一堆质数的最小公倍数会灰常灰常大

所以题解给了一个很牛逼的方法

那就是给 \(f\) 值转为自然对数来做。

即 \(f_{i,j} \Longleftrightarrow \ln{f_{i,j}}\)

于是转移时 \(\times w\) 变为 \(+ \ln{w}\)

\(Code\)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std; const int N = 1e4 + 5;
const double INF = 1e40;
int t , n , vis[N] , tot , pr[1300] , d[1300] , cnt , g[1300][N];
double f[1300][N] , ans; inline void getprime(int Mx)
{
vis[1] = 1;
for(register int i = 2; i <= Mx; i++)
{
if (!vis[i]) pr[++tot] = i;
for(register int j = 1; j <= tot && pr[j] * i <= Mx; j++)
{
vis[pr[j] * i] = 1;
if (i % pr[j] == 0) break;
}
}
} int main()
{
getprime(1e4);
scanf("%d" , &t);
for(; t; t--)
{
scanf("%d" , &n);
memset(f , 0 , sizeof f);
f[0][0] = log(1.0);
for(register int i = 1; i <= tot; i++)
for(register int j = 0; j <= n; j++)
{
f[i][j] = f[i - 1][j];
int w = pr[i];
while (j - w >= 0)
{
if (f[i - 1][j - w] + log(1.0 * w) > f[i][j]) f[i][j] = f[i - 1][j - w] + log(1.0 * w) , g[i][j] = w;
w *= pr[i];
}
}
ans = -INF;
int m , sum = 0;
for(register int i = 0; i <= n; i++)
if (f[tot][i] > ans) ans = f[tot][i] , m = i;
cnt = 0;
for(register int i = tot; i; i--)
{
if (g[i][m]) d[++cnt] = g[i][m] , sum += d[cnt];
m -= g[i][m];
}
while (sum < n) d[++cnt] = 1 , sum++;
sort(d + 1 , d + cnt + 1);
int k = 1;
for(register int i = 1; i <= cnt; i++)
{
for(register int j = 1; j < d[i]; j++)
printf("%d " , k + j);
printf("%d " , k) , k += d[i];
}
printf("\n");
}
}

JZOJ 3232. 【佛山市选2013】排列的更多相关文章

  1. 【佛山市选2013】JZOJ2020年8月7日T4 排列

    [佛山市选2013]JZOJ2020年8月7日T4 排列 题目 描述 一个关于n个元素的排列是指一个从{1, 2, -, n}到{1, 2, -, n}的一一映射的函数.这个排列p的秩是指最小的k,使 ...

  2. 【佛山市选2013】JZOJ2020年8月7日提高组T3 海明距离

    [佛山市选2013]JZOJ2020年8月7日提高组T3 海明距离 题目 描述 对于二进制串a,b,他们之间的海明距离是指两个串异或之后串中1的个数.异或的规则为: 0 XOR 0 = 0 1 XOR ...

  3. 【佛山市选2013】JZOJ2020年8月7日提高组T2 树环转换

    [佛山市选2013]JZOJ2020年8月7日提高组T2 树环转换 题目 描述 给定一棵N个节点的树,去掉这棵树的一条边需要消耗值1,为这个图的两个点加上一条边也需要消耗值1.树的节点编号从1开始.在 ...

  4. 【佛山市选2013】JZOJ2020年8月7日提高组T1 回文子序列

    [佛山市选2013]JZOJ2020年8月7日提高组T1 回文子序列 题目 描述 回文序列是指左右对称的序列.例如1 2 3 2 1是回文序列,但是1 2 3 2 2就不是.我们会给定一个N×M的矩阵 ...

  5. 纪中集训2020.02.05【NOIP提高组】模拟B 组总结反思——【佛山市选2010】组合数计算,生成字符串 PPMM

    目录 JZOJ2290. [佛山市选2010]组合数计算 比赛时 之后 JZOJ2291. [佛山市选2010]生成字符串 比赛时 之后 JZOJ2292. PPMM 比赛时 之后 JZOJ2290. ...

  6. JZOJ 1003 [ 东莞市选 2007 ] 拦截导弹 —— 递推

    题目:https://jzoj.net/senior/#main/show/1003 n^2 的话递推就可以啦. 代码如下: #include<iostream> #include< ...

  7. [JZOJ4024] [佛山市选2015] 石子游戏 解题报告

    Description     Alice 和 Bob 总喜欢聚在一起玩游戏(T_T),今天他(她)们玩的是一款新型的取石子游戏.游戏一开始有N堆石子,Alice 和 Bob 轮流取出石子.在每次操作 ...

  8. 【原创】开源.NET排列组合组件KwCombinatorics使用(二)——排列生成

           本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...

  9. 生成n个数的全排列【递归、回溯】

    下面讨论的是n个互不相同的数形成的不同排列的个数.毕竟,假如n个数当中有相同的数,那n!种排列当中肯定会有一些排列是重复的,这样就是一个不一样的问题了. /*===================== ...

  10. xamarin for vs2013

    安装需求(下载的包及版本) 先安装VS2013 然后到官网下Xamarin,运行后会自动下载以下文件 这是下载的详细列表 jdk-6u39-windows-i586.exe(69.73M) Andro ...

随机推荐

  1. 云小课|云小课教您如何选择Redis实例类型

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:购买Redis实例 ...

  2. 外部引入css样式报错Resource interpreted as Stylesheet but transferred with MIME type html/text

    Resource interpreted as Stylesheet but transferred with MIME type html/text 解决方法: 1.将content-type改为t ...

  3. 【每日一题】【暴力&双指针&动态规划】42. 接雨水-211130/220214

    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 方法1:暴力求解(超时) import java.util.*; public class Solu ...

  4. 【Java EE】Day07 HTML

    一.WEB概念 1.软件架构 C/S:安卓.QQ.迅雷,开发两端 B/S 2.资源分类 静态资源:浏览器内置解析引擎 HTML:展示内容 CSS:页面布局 JavaScript:控制页面元素,产生动态 ...

  5. go-dongle 0.2.0 版本发布了,一个轻量级、语义化的 golang 编码解码、加密解密库

    dongle 是一个轻量级.语义化.对开发者友好的 Golang 编码解码和加密解密库 Dongle 已被 awesome-go 收录, 如果您觉得不错,请给个 star 吧 github.com/g ...

  6. 大规模爬取(新浪为例子)网页之downloader、parser的封装(涉及编码等细节)

    import requests import cchardet import traceback from lxml import etree def downloader(url,timeout = ...

  7. 静态文件配置 django连接MySQL django模型层初识 ORM基本语句

    目录 静态文件配置 1. 问题描述 2. 静态文件 3. 资源访问 form表单属性补充 action method 请求方法 get请求 post请求 views层 request对象 reques ...

  8. docker-compose + mysql8.x 主从数据库配置

    0.准备 (略过docker的安装与镜像拉取) docker / docker-compose 安装 拉取 mysql 8.x 1. master和slave的mysql配置 master: [mys ...

  9. 教你铁威马NAS中如何进行阵列升级

    磁盘阵列 (RAID) 是磁盘阵列的管理工具.当TNAS 中安装的硬盘多于1个时,组建适当的磁盘阵列能提高硬盘的存储效率,提高数据的安全性. 磁盘阵列升级,比如,将原来是RAID 0 或者RAID 1 ...

  10. Codeforces Hello 2023 CF 1779 A~F 题解

    点我看题 A. Hall of Fame 先把不用操作就合法的情况判掉.然后发现交换LL,RR,RL都是没用的,只有交换LR是有用的,这样可以照亮相邻的两个位置.所以我们就是要找到一个位置i,满足\( ...