BZOJ 3990 [SDOI 2015] 排序 解题报告
这个题哎呀。。。细节超级多。。。
首先,我猜了一个结论。如果有一种排序方案是可行的,假设这个方案是 $S$ 。
那么我们把 $S$ 给任意重新排列之后,也必然可以构造出一组合法方案来。
于是我们就可以 $O(2^n)$ 枚举每个操作进不进行,再去判断,如果可行就 $ans$ += $|S|!$。
然而怎么判断呢?
我们按照操作种类从小到大操作。
假设我们现在在决策第 $i$ 种操作并且保证之前之后不需要进行种类编号 $< i$ 的操作。
那么我们只考虑那些位置在 $2^i+1$ 的位置的那些数。
我们先找到所有的非法位置,满足下列条件之一就是非法位置,设当前位置为 $pos$:
- 条件$1$:$A_{pos}$ 不能表示成 $a\times 2^i + 1$,其中 $a$ 为非负整数。
- 条件$2$:$A_{pos + 2^{i-1}} \ne A_{pos} + 2^{i-1}$。
满足以下三种情况之一即为无解:
- 如果有三个或以上个非法位置,那么显然就无解了。
- 如果没有非法位置,但是当前状态下必须要进行一次操作,那么无解。
- 如果有非法位置,但是当前状态下必须不进行操作,那么无解。
那么现在开始讨论:
当没有非法位置的时候,直接递归求解。
当只有一个非法位置的时候,交换 $A_{pos}$ 和 $A_{pos + 2^{i-1}}$,递归求解。
这里本来应该交换一个区间的,然而有用的其实只有 $A_{pos}$ 和 $A_{pos + 2^{i-1}}$ 这两个数。
因为其他的数字我们现在不会考虑,以后也更不用考虑了,反正保证是合法的,所以我们只交换这两个数。
当有两个非法位置的时候,设两个非法位置为 $pos_1$ 和 $pos_2$
我们把非法位置分两类:第一类是满足条件 $1$ 的,第二类是不满足条件 $1$ 但满足条件 $2$ 的。
- $type(pos_1) = 2$ && $type(pos_2) = 2$:可以有两种可能合法的交换:交换 $A_{pos_1}$ 和 $A_{pos_2}$ 或者交换 $A_{pos_1 + 2^{i - 1}}$ 和 $A_{pos_2 + 2^{i - 1}}$。
- $type(pos_1) = 2$ && $type(pos_2) = 1$:只有一种可能合法的交换:交换 $A_{pos_1 + 2^{i - 1}}$ 和 $A_{pos_2}$。
- $type(pos_1) = 1$ && $type(pos_2) = 2$:只有一种可能合法的交换:交换 $A_{pos_1}$ 和 $A_{pos_2 + 2^{i - 1}}$。
- $type(pos_1) = 1$ && $type(pos_2) = 1$:无解。
然后递归求解即可。注意每当交换完之后要判断原来的非法位置是否变合法了,如果还是非法的那么就直接判掉。
判断每个状态的复杂度:
$$\sum_{i=1}^{n}2^i\times\frac{2^n}{2^i} = \sum_{i=1}^{n}2^n = n\times 2^n$$
于是整个问题的复杂度就是:$O(n2^{2n})$ 的了。
然而常数很小很小,应该很难构造一组卡到上界的数据,所以跑得还是比较快的。。。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
#define N 12 + 5
#define SIZE 1 << 12 | 5 int n;
LL ans;
LL Fac[N];
int A[SIZE], Cnt[SIZE]; inline bool dfs(int state, int len)
{
if (len >> (n + )) return ;
int cnt = , pos_1, pos_2;
for (int i = ; i < ( << n); i += len)
{
int _i = i + (len >> );
if ((A[i] & (len - )) || A[_i] != A[i] + (len >> ))
{
cnt ++;
if (cnt == ) pos_1 = i;
else if (cnt == ) pos_2 = i;
else return ;
}
}
if ((state & ) == && cnt) return ;
if ((state & ) && !cnt) return ;
if (!cnt) return dfs(state >> , len << );
if (cnt == )
{
swap(A[pos_1], A[pos_1 + (len >> )]);
bool ok = dfs(state >> , len << );
swap(A[pos_1], A[pos_1 + (len >> )]);
return ok;
}
if (cnt == )
{
bool ok = ;
if ((A[pos_1] & (len - )) && (A[pos_2] & (len - ))) return ;
else if (A[pos_1] & (len - ))
{
swap(A[pos_1], A[pos_2 + (len >> )]);
if (A[pos_1] + (len >> ) != A[pos_1 + (len >> )]) ok = ;
if (A[pos_2] + (len >> ) != A[pos_2 + (len >> )]) ok = ;
if (ok) ok = dfs(state >> , len << );
swap(A[pos_1], A[pos_2 + (len >> )]);
return ok;
}
else if (A[pos_2] & (len - ))
{
swap(A[pos_2], A[pos_1 + (len >> )]);
if (A[pos_1] + (len >> ) != A[pos_1 + (len >> )]) ok = ;
if (A[pos_2] + (len >> ) != A[pos_2 + (len >> )]) ok = ;
if (ok) ok = dfs(state >> , len << );
swap(A[pos_2], A[pos_1 + (len >> )]);
return ok;
}
else
{
swap(A[pos_1], A[pos_2]);
if (A[pos_1] + (len >> ) != A[pos_1 + (len >> )]) ok = ;
if (A[pos_2] + (len >> ) != A[pos_2 + (len >> )]) ok = ;
if (ok) ok = dfs(state >> , len << );
swap(A[pos_1], A[pos_2]);
if (ok) return ; ok = ;
swap(A[pos_1 + (len >> )], A[pos_2 + (len >> )]);
if (A[pos_1] + (len >> ) != A[pos_1 + (len >> )]) ok = ;
if (A[pos_2] + (len >> ) != A[pos_2 + (len >> )]) ok = ;
if (ok) ok = dfs(state >> , len << );
swap(A[pos_1 + (len >> )], A[pos_2 + (len >> )]);
return ok;
}
}
} int main()
{
#ifndef ONLINE_JUDGE
freopen("3990.in", "r", stdin);
freopen("3990.out", "w", stdout);
#endif scanf("%d", &n);
Fac[] = ;
for (int i = ; i <= n; i ++)
Fac[i] = Fac[i - ] * i;
for (int i = ; i <= ( << n); i ++)
{
scanf("%d", A + i - );
A[i - ] --;
Cnt[i] = Cnt[i - (i & -i)] + ;
}
for (int s = ; s < ( << n); s ++)
if (dfs(s, )) ans += Fac[Cnt[s]];
printf("%lld\n", ans); #ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return ;
}
3990_Gromah
BZOJ 3990 [SDOI 2015] 排序 解题报告的更多相关文章
- BZOJ 3998 [TJOI 2015] 弦论 解题报告
这是一道后缀自动机经典题目. 对于 $t=0$ 的情况:每个节点都代表一个子串,所以我们给每个节点的 $Size$ 都记为 $1$, 对于 $t=1$ 的情况:我们只给 $last$ 节点的 $Siz ...
- BZOJ 3997 [TJOI 2015 组合数学] 解题报告
这个题我脑洞了一个结论: 首先,我们定义满足以下条件的路径为“从右上到左下的路径”: 对于路径上任何不相同的两个点 $(x_1, y_1)$,$(x_2, y_2)$,都有: $x_1\neq x_2 ...
- BZOJ 3996 [TJOI 2015] 线性代数 解题报告
首先,我们可以得到: $$D = \sum_{i=1}^{n}\sum_{j=1}^{n}a_i\times a_j\times b_{i,j} - \sum_{i=1}^{n}a_i\times c ...
- [BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT)
[BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT) 题面 小C有一个集合S,里面的元素都是小于质数M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数 ...
- 【九度OJ】题目1023:EXCEL排序 解题报告
[九度OJ]题目1023:EXCEL排序 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1023 题目描述: E ...
- 【九度OJ】题目1185:特殊排序 解题报告
[九度OJ]题目1185:特殊排序 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1185 题目描述: 输入一系 ...
- 【九度OJ】题目1061:成绩排序 解题报告
[九度OJ]题目1061:成绩排序 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1061 题目描述: 有N个学 ...
- 【九度OJ】题目1202:排序 解题报告
[九度OJ]题目1202:排序 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1202 题目描述: 对输入的n个 ...
- 【九度OJ】题目1190:大整数排序 解题报告
[九度OJ]题目1190:大整数排序 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1190 题目描述: 对N个长度最长可达 ...
随机推荐
- 最大公约数与欧几里得(Euclid)算法
---恢复内容开始--- 记a, b的最大公约数为gcd(a, b).显然, gcd(a,b)=gcd(|a|,|b|). 计算最大公约数的Euclid算法基于下面定理: [GCD递归定理]对于任意非 ...
- Lodash Filter
var persons = [{name:'1',age:'20'}, {name:'2', age:'25'}];_.filter(persons, {'age': '25'}); //return ...
- 面试之SQL
1. 查询性能优化:从数据库查询数据时,你一定遇到过查询很慢的情况,请问你是怎么处理的. 答: 遇到的问题描述:是遇到过这种情况,我们给客户做过一款软件,日志库搜集了6000万条数据,显示.查询时候慢 ...
- Java内存分配全面浅析(转)
原文引自CSDN: 本文将由浅入深详细介绍Java内存分配的原理,以帮助新手更轻松的学习Java.这类文章网上有很多,但大多比较零碎.本文从认知过程角度出发,将带给读者一个 ...
- RabbitMQ 原文译03--发布和订阅
发布/订阅 在之前的案例中我们创建了一个工作队列,这个工作队列的实现思想就是一个把每一个任务平均分配给每一个执行者,在这个篇文章我们会做一些不一样的东西,把一个消息发送给多个消费者,这种模式就被称作& ...
- SSH无密码登陆问题解决
转载 http://my.oschina.net/hunzi/blog/10687 安装好Cygwin后,SSH需要设置为无密码登陆, 首先查看是ssh还是ssh2:ls -l `which ssh` ...
- Google maps not working IE11
参考原因: http://www.easypagez.eu/maps/ieworking.html 如果还不行的话,在map的样式上加上width:100%;height:100% ;position ...
- ODBC连接MySQL出现"E_FAIL"错误
ODBC不能处理这种格式的数据:0000-00-00,将其更新为正常的时间即可解决
- Hudson的安装配置
Hudson的安装配置 目录 一.正文... 2 1.安装配置jdk. 2 2.安装配置tomcat7. 2 3.安装Hudson. 2 4.启动tomcat. 2 5.初识Hudson. 3 6 ...
- 11_Jaxws常用注解
[不使用注解] 默认namespace是服务类包名的倒序 默认portType是服务类的类名 ............... 注解的所起的作用: Jaxws提供的注解可以对WebService的接口规 ...