20210804 noip30
考场
第一眼感觉 T1 是状压 DP,弃了。T2 好像也是 DP???看上去 T3 比较可做。
倒序开题。T3 暴力是 \(O(pn\log p)\)(枚举 \(x\),二分答案,看能否分成合法的不超过 \(k\) 组),先写个随机化,和暴力拍了一下发现正确率不太行,退火收敛太慢,只能爬山了,结果还不如直接随机???打表发现峰值特别多。。。死了。强行让退火快速收敛+随机化卡时到 0.98s,拍了拍发现 \(n,p\le5000\) 的时候正确率还行。没注意时间,写完 8.30 了。
T2 完全不会做,直接暴力。手玩数据发现和逆序对有关,但还是只会判无解,后来写了个复杂度不明(也许是 \(O(ans)\))的做法,一分也没骗到。不会造数据,随机了一些发现都是无解。。。爬了
9.30 才开 T1,想了想 DP(根本就不是 DP 啊)就写暴力了。写了 \(O(2^nn\sum m)\) 的暴力,分 \(\sum m\) 的大小用 bitset 或 bool 做背包,发现有一个 \(n=17,m\le2\times10^4\) 的点不会做(其实是 \(O(3^n)\) 枚举每个数不要/放第一个集合/放第二个),一直想到结束。
res
rk14 30+20+50
T3 退火还是太慢,导致后面的点全 T 了。(不然能拿 60~70pts)
rk1 yzf 45+100+50
rk3 牛宏昊 90+20+40
rk5 ycx 75+20+50
rk6 wcr 80+0+60
rk7 刘荣信 15+20+100
rk9 zjj 35+20+70
总结
主要死在了 T1,如果不从 DP 的方向想拿到 70pts 及以上还是比较容易的,以后不要直接确定一个方向,先直接想想,想不出来再根据感觉想特定的算法。
乱搞能力还是太死板,这场的 T1 T3 数据都水,各种做法都能拿到高分甚至 A
毛一琛
meet in the middle
先爆算前 \(\frac n2\) 个数的状态,记下差值和并集。
再枚举后 \(\frac n2\) 个,对于每个差值查和前 \(\frac 2n\) 中和它相同的状态(最多 \(2^{\frac n2}\) 个),然后把两个状态的或计入答案。
时间复杂度 \(O(6^{\frac n2})\)。题解说调整前后的大小能更快,但实测 \(\frac n3,\frac{2n}3\) 都不如 \(\frac n2\)
我选择了用 map 离散化差值,vector 存每个差值的状态,bool 数组去重,貌似不是正解(跑得很慢)
code
const int N = 22;
int n,a[N];
int m,ind,ans;
bool vis[1<<N];
unordered_map<int,int> id;
vector<int> state[1<<N];
void dfs1(int u,int del,int s) {
if( u > m ) {
if( !id.count(del) ) id[del] = ++ind;
state[id[del]].pb(s);
return;
}
dfs1(u+1,del,s);
dfs1(u+1,del+a[u],s|(1<<u-1));
dfs1(u+1,del-a[u],s|(1<<u-1));
}
void dfs2(int u,int del,int s) {
if( u > n ) {
if( !id.count(del) ) return;
int i = id[del];
for(int t : state[i]) vis[s|t] = 1;
return;
}
dfs2(u+1,del,s);
dfs2(u+1,del+a[u],s|(1<<u-1));
dfs2(u+1,del-a[u],s|(1<<u-1));
}
signed main() {
read(n); m = n/2.0;
For(i,1,n) read(a[i]);
dfs1(1,0,0);
dfs2(m+1,0,0);
for(int i = 1, j = 1<<n; i < j; ++i) ans += vis[i];
write(ans);
return iocl();
}
毛二琛
下文将 \([0,n-1]\) 对应到 \([1,n]\)
首先如果有 \(i=p_i\) 那么无解,但数据中没有,所以不用判
问题可以转化为 \(n-1\) 个数排列,对 \(i,i+1\) 的前后顺序有要求(这点保证了每个排列对应一个答案),求方案数。
先处理前后顺序。设 \(cmp[i]=0\) 表示 \(i\) 在 \(i+1\) 的前面,\(=1\) 表示在后面。若 \(i<p_i\),那么 \(cmp[i-1]=1\)(先要把数 \(p_i\) 从 \(i\) 换到 \(i+1\) 才能换 \(i-1,i\)),\(cmp[i..p_i-2]=0\)(数 \(p_i\) 要从 \(i\) 一直向右换到 \(p_i\),期间换了左边的才能换右边,不然数 \(p_i\) 就无法继续向右了),\(cmp[p_i-1]=1\)(换 \(p_i-1,p_i\) 后数 \(p_i\) 一定在 \(p_i\) 上,此后换 \(p_i,p_i+1\) 会导致数 \(p_i\) 被换离);\(i>p_i\) 的情况同理。
考虑 DP。设 \(f[i,j]\) 为前 \(i\) 个数中 \(i\) 排在第 \(j\) 位的方案数,转移:
\sum_{k=j}^{i-1}f[i-1,k],cmp[i-1]=1
\\
\sum_{k=1}^{j-1}f[i-1,k],cmp[i-1]=0
\end{matrix}\right.
\]
\(cmp[i-1]=1\) 时 \(k\in[j,i-1]\) 是因为在前 \(i\) 个数中 \(i-1\) 排在第 \(j\) 位之后,那么在前 \(i-1\) 个数中就要排在 \([j,i-1]\),可以看作将 \(i\) 插进前 \(i-1\) 个数排列的第 \(j\) 位,那么原来的 \(j..i-1\) 位就要向右移一位。第二维可以前缀和优化,时间复杂度 \(O(n^2)\)
code
const int N = 5e3+5, mod = 1e9+7;
int n,a[N];
int f[N][N],sum[N][N];
bool cmp[N];
signed main() {
read(n);
For(i,1,n) read(a[i]), ++a[i];
for(int i = 1; i < n; ++i)
if( i < a[i] ) cmp[i-1] = cmp[a[i]-1] = 1;
else for(int j = a[i]; j < i-1; ++j) cmp[j] = 1;
f[1][1] = sum[1][1] = 1;
for(int i = 2; i < n; ++i) {
if( cmp[i-1] ) For(j,1,i) f[i][j] = (sum[i-1][i-1]-sum[i-1][j-1]+mod)%mod;
else For(j,1,i) f[i][j] = sum[i-1][j-1];
For(j,1,n) sum[i][j] = (sum[i][j-1] + f[i][j]) %mod;
}
write(sum[n-1][n-1]);
return iocl();
}
毛三琛
需要加一个优化:随机枚举 \(x\),\(O(n)\) 判断在当前答案下能否分成不超过 \(k\) 组,如果可以再去二分,时间复杂度 \(O(qn+n\log n\log q)\)
code
const int N = 1e4+5;
int n,p,m,a[N];
int ans,b[N],q[N];
mt19937 mt(time(0));
bool check(int x) {
int res = 1, sum = 0;
For(i,1,n) {
if( b[i] > x ) return 0;
if( sum+b[i] <= x ) sum += b[i];
else ++res, sum = b[i];
}
return res <= m;
}
int calc(int x) {
int l = 1, r = ans;
while( l < r ) {
int mid = l+r>>1;
if( check(mid) ) r = mid;
else l = mid+1;
}
return l;
}
signed main() {
read(n,p,m);
For(i,1,n) read(a[i]), ans += a[i];
for(int i = 0; i < p; ++i) q[i] = i;
shuffle(q,q+p,mt);
for(int i = 0; i < p; ++i) {
For(j,1,n) b[j] = (a[j] + q[i]) %p;
if( check(ans) ) ans = calc(q[i]);
}
write(ans);
return iocl();
}
20210804 noip30的更多相关文章
- noip30
T1 一眼看,觉得是个状压,然而又觉得不太行,去打暴力了,然而暴力都打挂的我biss. 正解: 还是暴力,考虑 \(meet \; in \; the \; middle\) 显然对于每个数,只有三种 ...
- win 常用修复蓝屏,系统比对最后更新20210804
您可以尝试以下方案: 在管理员命令提示符下键入以下命令:Dism /Online /Cleanup-Image /ScanHealth这条命令将扫描全部系统文件并和官方系统文件对比,扫描计算机中的不一 ...
- 调用免费API查询全年工作日、周末、法定节假日、节假日调休补班数据
前言 日常开发中,难免会用到判断今天是工作日.周末.法定节假日.节假日调休补班做一些业务处理,例如:仅在上班时间给用户推送消息.本文记录调用免费API查询全年工作日.周末.法定节假日.节假日调休补班数 ...
- 阿里云RocketMQ定时/延迟消息队列实现
新的阅读体验:http://www.zhouhong.icu/post/157 一.业务需求 需要实现一个提前二十分钟通知用户去做某件事的一个业务,拿到这个业务首先想到的最简单得方法就是使用Redis ...
- SprintBoot简单入门
1.什么是SpringBoot SpringBoot是基于Spring的基础上提供了一套全新的框架,其目的是为了在开发时简化Spring的相关配置及开发过程.在SpringBoot未出来之前,准备搭建 ...
- 用Python预测双色球福利彩票中奖号码(请不要当真)
前言 双色球是中国福利彩票的一种玩法. 红球一共6组,每组从1-33中抽取一个,六个互相不重复.然后蓝球是从1-16中抽取一个数字,这整个组成的双色球 python从零基础入门到实战 今天,我们就用P ...
- 破解加速乐-java
记录一哈自己遇到的简单站点的破解 Talk is cheap,show you the code! import com.google.gson.Gson; import com.google.gso ...
- (11)MySQL进阶篇SQL优化(InnoDB锁问题排查与解决)
1.概述 前面章节之所以介绍那么多锁的知识点和示例,其实最终目的就是为了排查与解决死锁的问题,下面我们把之前学过锁知识重温与补充一遍,然后再通过例子演示下如果排查与解决死锁. 2.前期准备 ●数据库事 ...
- linux centos7 df命令
2021-08-04 1. df 命令简介 linux 中 df 命令的功能是用来检查 linux 服务器的文件系统的磁盘空间占用情况.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信 ...
随机推荐
- thinkPHP5 5.0.23 远程代码执行漏洞
修改数据包 POST /index.php?s=captcha HTTP/1.1 Host: 192.168.49.2:8080 User-Agent: Mozilla/5.0 (Macintosh; ...
- Oracle数据泵导入的时候创建索引是否会使用并行?
一.疑问,Oracle数据泵导入的时候创建索引是否会使用并行? 某客户需要使用数据泵进行迁移,客户咨询导入的时间能不能加快一点. 那么如何加快导入的速度呢? 多加一些并行,那么创建索引内部的索引并行度 ...
- 采用Jpcap+redis+线程 设备网络流量监控 应用实战实例
.personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...
- POSIX多线程编程-条件变量pthread_cond_t
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...
- Create Virtual Network with Virtualbox
Create a virtual machine "ubs1" with ubuntu server 12.04, set its network as Host-only; St ...
- 在Django中使用Channels功能
前言:最近后台写游戏更新版本功能,简单就是前端发送更新请求,后端需要对很多台服务器进行更新和各种操作,本来想着实现不难,后来发现因为后端需要执行很长时间,前端返回报错,后端会执行完毕,但是前端先断开了 ...
- 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q ...
- java批量下载文件为zip包
批量下载文件为zip包的工具类 package com.meeno.trainsys.util; import javax.servlet.http.HttpServletRequest; impor ...
- prism 的学习网站
C#的学习网址: https://www.cnblogs.com/zh7791
- 十四:Servlet3.0的动态
动态的创建是为了简化配置文件的.对于我们创建的servlet,filter和listener后可以使用.这也是注解的另外一种替代方式. package com.hotusm.dynamic; impo ...