T1

一眼看,觉得是个状压,然而又觉得不太行,去打暴力了,然而暴力都打挂的我biss。

正解:

还是暴力,考虑 \(meet \; in \; the \; middle\)

显然对于每个数,只有三种状态,

  1. 不选。
  2. 放入左边集合。
  3. 放入右边集合。

用当前的和,加减当前的数可以表示。

搜索 \([1,mid]\) 时,记录每种 \(sum\) 是选择了那些所组合出来的,0,1表示选还是没选,用 \(bitset\) 来记录状态。

搜索 \([mid+1,n]\) 时,每求出了一个 \(sum\) ,就需要前边那一半出现 \(-sum\) 的方案来得到总的方案数,显然 \(-sum\) 的方案数跟 \(sum\) 的方案数是等价的。

用的 \(unordered\_map\) 里边套了个 \(bitset\),下标是 \(int\) 类型的,表示组合出 \(sum\) 所选的数。

Code
#include<bitset>
#include<cstdio>
#include<algorithm>
#include<unordered_map>
#define re register
using std::sort;
using std::bitset;
using std::unordered_map;
const int MAX = 1<<11;
namespace OMA
{
int n,m[21],mid,ans;
bitset<MAX>jud[MAX],tmp;
unordered_map<int,bitset<MAX> >vis;
inline void dfsl(int p,int sum,int opt)
{
if(p==mid+1)
{ vis[sum].set(opt); return ; }
dfsl(p+1,sum,opt),dfsl(p+1,sum+m[p],opt|1<<p),dfsl(p+1,sum-m[p],opt|1<<p);
}
inline void dfsr(int p,int sum,int opt)
{
if(p==n+1)
{
if(vis[sum].count())
{ tmp = vis[sum]&(~jud[opt]),ans += tmp.count(),jud[opt] |= tmp; }
return ;
}
dfsr(p+1,sum,opt),dfsr(p+1,sum+m[p],opt|(1<<(p-(mid+1)))),dfsr(p+1,sum-m[p],opt|(1<<(p-(mid+1))));
}
signed main()
{
scanf("%d",&n),mid = n/2;
for(re int i=1; i<=n; i++)
{ scanf("%d",&m[i]); }
sort(m+1,m+1+n),dfsl(1,0,0),dfsr(mid+1,0,0);
printf("%d\n",ans-1);
return 0;
}
}
signed main()
{ return OMA::main(); }

然后发现这份代码在本机编译会CE,因为用了\(unordered\_map\) ,

以下内容摘自oi-wiki,

在 C++11 之前,无序关联式容器属于 C++ 的 TR1 扩展。所以,如果编译器不支持 C++11,在使用时需要在头文件的名称中加入 tr1/ 前缀,并且使用 std::tr1 命名空间。如 #include <unordered_map> 需要改成 #include <tr1/unordered_map>;std::unordered_map 需要改为 std::tr1::unordered_map(如果使用 using namespace std;,则为 tr1::unordered_map)。

但其实直接在终端里开c++11就可以了

T2

\(next_\;permutation\) 可以氵20pts,然而我不会拼 \(permutation\) biss。

正解:

是个dp,考虑排列p中的每个数怎样才能被移动到该到的地方。

这显然是一些相邻的交换的顺序关系,即形如“ \(q\) 中 \(i\) 在 \(i+1\) 前 \(or\) 后”的限制。

问题转化为一个大小为 \(n-1\) 的排列,某些地方限定了相邻两数的大小关系,求方案数。

直接简单DP即可,\(dp_{i,j}\) 表示前i个数,第i个数在前i个数中是第j小的。前缀和优化。

\(O(n^2)\)

Code
咕咕咕

T3

同样是暴力,有的人a了,有的人wa了。

正解:

暴力

好吧,其实应该算是二分答案,枚举x,计算当前的质量,二分最大值,上界为当前的质量和,判断当前最大值为 \(mid\) 时所分的背包数是否满足 \(\le k\), 同时注意,若当前的质量中有一个大于 \(mid\) ,那显然,当前 \(mid\) 肯定不满足条件,直接break即可。

然后发现,这个T了,只有40pts,考虑如何去优化。

题解说不难发现,二分前,先判断一下是否比当前答案要优,不是直接continue,然后就A了。

至于题解里提到的,随机枚举顺序,好像并没有什么大的作用,或者说,我写假了???QAQ

Code
#include<cstdio>
#include<climits>
#include<algorithm>
#define MAX 10010
#define re register
#define INF INT_MAX
using std::random_shuffle;
namespace OMA
{
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
int sum[MAX],ans=INF;
int n,p,k,a[MAX],b[MAX],x[MAX];
inline bool check(int now)
{
int res = 0,cnt = 1;
for(re int i=1; i<=n; i++)
{
if(b[i]>now)
{ return false; }
if(res+b[i]>now)
{ res = 0,cnt++; }
res += b[i];
}
return cnt<=k;
}
inline int min(int a,int b)
{ return a<b?a:b; }
signed main()
{
n = read(),p = read(),k = read();
for(re int i=1; i<=n; i++)
{ a[i] = read(); }
for(re int i=0; i<=p-1; i++)
{ x[i+1] = i; }
random_shuffle(x+1,x+1+p);
for(re int i=1; i<=p; i++)
{
int res,l = 0,r = 0;
for(re int j=1; j<=n; j++)
{ r += (b[j] = (a[j]+x[i])%p); }
if(!check(ans))
{ continue ; }
while(l<=r)
{
int mid = (l+r)>>1;
if(check(mid))
{ r = mid-1,res = mid; }
else
{ l = mid+1; }
}
//printf("res=%d\n",res);
ans = min(ans,res);
}
printf("%d\n",ans);
return 0;
}
}
signed main()
{ return OMA::main(); }

反思总结:

  1. 一些STL的东西还是要会的,骗分或者打正解的时候可能会用到,不能不会,比如 \(next\_premutation\) 。

  2. 不能瞧不起暴力,但也不能直接硬怼暴力,万一加个减枝就过了呢。

  3. 注意心态问题,不能自暴自弃。

noip30的更多相关文章

  1. 20210804 noip30

    考场 第一眼感觉 T1 是状压 DP,弃了.T2 好像也是 DP???看上去 T3 比较可做. 倒序开题.T3 暴力是 \(O(pn\log p)\)(枚举 \(x\),二分答案,看能否分成合法的不超 ...

随机推荐

  1. XCTF Normal_RSA

    这题本来算是很常规的rsa了,下载附件 发现有个公钥文件,还有一个加密文件,这种题之前有遇到一次,做法和这个类似,上次那个是用rsa的库,直接解的,这次直接用常规的,好像更简单,记录下模板 记事本打开 ...

  2. Jmeter之cokie管理器和http默认值

    根据上文中,都配置好以后就可以开始启动了,点击启动,线程组里面就会开始记录你的网页请求.这里使用CNode网站做测试.我分别记录进行了"登入","话题创建",& ...

  3. JSP核心技术

    一.JSP基本概念 JSP是Java Server Page 的简称,跟Servlet 一样可以动态生成HTML响应,文件命名为XXX.jsp JSP 与Servlet 的区别: jsp经编译后就变成 ...

  4. Linux常用命令 day day up系列3

    一.命令执行的优先级二.Linux目录结构三.cat--查看文件内容四.more--查看文件内容五.less--查看文件内容六.head.tail--查看文件内容七.wc--统计文件内容八.grep- ...

  5. DHCP与配置命令

    1. DHCP简介 2. DHCP主要用途 3. 使用DHCP的好处 4.DHCP经典应用模式 5.DHCP交互过程 DHCP的IP地址自动获取工作原理 6.DHCP中继    应用场景   工作原理 ...

  6. 泛型(8)-Java7的"菱形"语法与泛型构造器

    正如泛型方法允许在方法签名中声明泛型形参一样,Java也允许在构造器签名中声明泛型形参,这样就产生了所谓的泛型构造器. package com.j1803;class Foo{ public < ...

  7. 手写系列-实现一个铂金段位的 React

    一.前言 本文基于 https://pomb.us/build-your-own-react/ 实现简单版 React. 本文学习思路来自 卡颂-b站-React源码,你在第几层. 模拟的版本为 Re ...

  8. lucene 入门简介

    Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能.Lucene 目前是 Apache Jakarta 家族中的一个开源项目. ...

  9. P7324 [WC2021] 表达式求值

    P7324 [WC2021] 表达式求值 闲话 WC2021 我只得了 20 分,三道题总共 20 分.我是下场了突然后知后觉这件事的,主要原因是我开了 C++11,然后 T1 T2 都没分了.在洛谷 ...

  10. 【洛谷P2800又上锁妖塔】动态规划

    分析 考虑上一层还是上两层还是爬上去 AC代码 #include <bits/stdc++.h> using namespace std; int f[1000005],a[1000005 ...