CF1290F Making Shapes

题目描述

一位 怀好意的拉题人的翻译:

题解

前置知识:计算几何,背包DP,数位DP。

首先容易发现,如果你选的每个向量的系数 cic_ici​(可能为0)确定了,那么把它们按极角排序后的凸包是唯一确定的,所以我们把问题转换为求不同的系数有多少组。

如果我们把两坐标按正负分开考虑,就会发现
∑xi>0cixi=∑xj<0cj(−xj)∑yi>0ciyi=∑yj<0cj(−yj)\sum_{x_i>0}c_ix_i=\sum_{x_j<0}c_j(-x_j)\\ \sum_{y_i>0}c_iy_i=\sum_{y_j<0}c_j(-y_j)\\ xi​>0∑​ci​xi​=xj​<0∑​cj​(−xj​)yi​>0∑​ci​yi​=yj​<0∑​cj​(−yj​)这是因为最终所有线段必须围城闭合的凸多边形,所以向量和为0。而这个 mmm 的限制呢?显然两坐标的极差就等于所有同号的 xxx 或 yyy 的和,也就是说
∑xi>0cixi≤m且∑yi>0ciyi≤m\sum_{x_i>0}c_ix_i\le m\,\,且\,\,\sum_{y_i>0}c_iy_i\le m xi​>0∑​ci​xi​≤m且yi​>0∑​ci​yi​≤m这就是为什么上面的向量和为零要把正负分开写而不是直接求和。

显然,如果 mmm 很小的话,这是可以做背包的。

但是这题 mmm 很大,不能用常规的背包。那怎么办呢,这时一般要放弃背包而想想其它办法…

不,我们可以想办法优化背包!

一般背包的优化有哪些呢?最著名的莫过于倍增优化了。传统的倍增优化是先分开考虑每种物品,然后用倍增拆开它的数量。这里我们把它颠倒一下,先统一用倍增拆开向量的系数,拆成二进制的30位,然后再考虑每个向量的系数在每个二进制位上是否有值。
这时显然是会产生进位的,所以就要从低位到高位考虑。每次转移需要考虑 2n2^n2n 种情况,进位最多有 ∑xi≤4n\sum x_i\le4n∑xi​≤4n,但是这题 nnn 和 xix_ixi​ 非常小,所以这么DP居然是可行的。

这就是更高级的倍增优化:考虑进位的数位背包DP

具体地,我们需要记录7个状态(7维DP):
dp[w][a][b][c][d][p=0/1][q=0/1]dp[w][a][b][c][d][p=0/1][q=0/1]dp[w][a][b][c][d][p=0/1][q=0/1],表示
当前考虑第 www 个二进制位,
正的 xix_ixi​ 产生的进位为 aaa,
负的 xix_ixi​ 产生的进位为 bbb,
正的 yiy_iyi​ 产生的进位为 ccc,
负的 yiy_iyi​ 产生的进位为 ddd,
ppp:∑xi>0cixi\sum_{x_i>0}c_ix_i∑xi​>0​ci​xi​ 的前 w−1w-1w−1 位是否 ≤m\le m≤m,
qqq:∑yi>0ciyi\sum_{y_i>0}c_iy_i∑yi​>0​ci​yi​ 的前 w−1w-1w−1 位是否 ≤m\le m≤m。

转移的时候要保证每个二进制位上∑xi>0cixi=∑xj<0cj(−xj)\sum_{x_i>0}c_ix_i=\sum_{x_j<0}c_j(-x_j)∑xi​>0​ci​xi​=∑xj​<0​cj​(−xj​),∑yi>0ciyi=∑yj<0cj(−yj)\sum_{y_i>0}c_iy_i=\sum_{y_j<0}c_j(-y_j)∑yi​>0​ci​yi​=∑yj​<0​cj​(−yj​),且保证最高位没有进位,ppp 和 qqq 都为1。

最后要减去系数全为0的1种情况,因为要求凸包面积非0。

总复杂度为 O(2n(4n)4log⁡m)O(2^n(4n)^4\log m)O(2n(4n)4logm),写成记忆化搜索会方便一些。

代码

#include<bits/stdc++.h>//JZM yyds!!
#define ll long long
#define uns unsigned
#define IF (it->first)
#define IS (it->second)
#define END putchar('\n')
using namespace std;
const int MAXN=-1;
const ll INF=1e18;
inline ll read(){ll x=0;bool f=1;char s=getchar();while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+(s^48),s=getchar();return f?x:-x;
}
int ptf[30],lpt;
inline void print(ll x,char c='\n'){if(x<0)putchar('-'),x=-x;ptf[lpt=1]=x%10;while(x>9)x/=10,ptf[++lpt]=x%10;while(lpt)putchar(ptf[lpt--]^48);if(c>0)putchar(c);
}
inline ll lowbit(ll x){return x&-x;}const ll MOD=998244353;
int n,k,x[10],y[10];
ll m,ans;
inline ll ads(ll x){return x>0?x:-x;}
inline void ad(int&a,int b){a+=b;if(a>=MOD)a-=MOD;}
int dp[32][22][22][22][22][2][2];
inline int DP(int w,int a,int b,int c,int d,bool p,bool q){if(w==30)return (!a&&!b&&!c&&!d&&p&&q);if(dp[w][a][b][c][d][p][q]>0)return dp[w][a][b][c][d][p][q]-1;int&res=dp[w][a][b][c][d][p][q],e=(m>>w)&1;for(int s=0;s<(1<<n);s++){int aa=a,bb=b,cc=c,dd=d;for(int i=1;i<=n;i++)if((s>>(i-1))&1){if(x[i]>=0)aa+=x[i];else bb-=x[i];if(y[i]>=0)cc+=y[i];else dd-=y[i];}if((aa&1)==(bb&1)&&(cc&1)==(dd&1))ad(res,DP(w+1,aa>>1,bb>>1,cc>>1,dd>>1,(aa&1)<e||((aa&1)==e&&p),(cc&1)<e||((cc&1)==e&&q)));}return res++;
}
signed main()
{n=read(),m=read();for(int i=1;i<=n;i++)x[i]=read(),y[i]=read();print((DP(0,0,0,0,0,1,1)-1+MOD)%MOD);return 0;
}

CF1290F Making Shapes——数位背包DP相关推荐

  1. 【LibreOJ】#6395. 「THUPC2018」城市地铁规划 / City 背包DP+Prufer序

    [题目]#6395. 「THUPC2018」城市地铁规划 / City [题意]给定n个点要求构造一棵树,每个点的价值是一个关于点度的k次多项式,系数均为给定的\(a_0,...a_k\),求最大价值 ...

  2. 背包dp的核心思想(动态规划)

    背包dp 突然发现我一直没有真正理解背包,真正的背包应该是用空间换时间的一种dp方法,本质上就是n个物品选或不选,理论上有2n2^n2n种可能结果,但是背包利用的就是值域很小这一特点来重叠子结构,所以 ...

  3. Codeforces 864E Fire(背包DP)

    背包DP,决策的时候记一下 jc[i][j]=1 表示第i个物品容量为j的时候要选,输出方案的时候倒推就好了 #include<iostream> #include<cstdlib& ...

  4. 【bzoj4007】[JLOI2015]战争调度 暴力+树形背包dp

    题目描述 给你一棵 $n$ 层的完全二叉树,每个节点可以染黑白两种颜色.对于每个叶子节点及其某个祖先节点,如果它们均为黑色则有一个贡献值,如果均为白色则有另一个贡献值.要求黑色的叶子节点数目不超过 $ ...

  5. HDU 1011 Starship Troopers 树形+背包dp

    http://acm.hdu.edu.cn/showproblem.php?pid=1011   题意:每个节点有两个值bug和brain,当清扫该节点的所有bug时就得到brain值,只有当父节点被 ...

  6. 【bzoj1222】[HNOI2001]产品加工 背包dp

    题目描述 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机器共同进行加工 ...

  7. 【bzoj4753】[Jsoi2016]最佳团体 分数规划+树形背包dp

    题目描述 JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一位编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY自己看上的.为了 ...

  8. 【bzoj5072】[Lydsy十月月赛]小A的树 树形背包dp

    题目描述 给出一棵n个点的树,每个点有黑白两种颜色.q次询问,每次询问给出x和y,问能否选出一个x个点的联通子图,使得其中黑点数目为y. 输入 第一行一个正整数 T 表示数据组数. 对于每一组数据,第 ...

  9. 【背包DP练习】洛谷 P5020货币系统 P1757通天之分组背包 P1064[NOIP2006 提高组]金明的预算方案 P5322 [BJOI2019]排兵布阵

    洛谷 P5020货币系统 https://www.luogu.com.cn/problem/P5020 思路是把货币从小到大排序,然后按顺序依次完全背包dp,每次dp检查i-1种面值的货币能不能凑出第 ...

  10. hdu 5234 Happy birthday 背包 dp

    Happy birthday Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...

最新文章

  1. [洛谷P2742]【模板】二维凸包([USACO5.1]圈奶牛Fencing the Cows)
  2. ML之NBLoR:利用NB(朴素贝叶斯)、LoR(逻辑斯蒂回归)算法(+TfidfVectorizer)对Rotten Tomatoes影评数据集进行文本情感分析—五分类预测
  3. Android开发之关于transformDexArchiveWithExternalLibsDexMergerForDebug java.lang.OutOfMemoryError问题的参考解决方案
  4. 执行work count程序报错Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster
  5. 智能控制在计算机领域的应用,智能控制的主要应用领域
  6. 【测试】软件测试之测试用例的设计方法
  7. AI+IoT行业“飞轮效应”凸显,全球云服务能力将发挥关键作用
  8. 子在川上曰:nginx的安装和配置、node服务器的配置、mongdb的安装、pm2进行项目动态管理
  9. UDP协议全面实验分析详解
  10. 计算机组成原理DMA的全称,直接存贮器存取(DMA) -计算机组成原理与汇编语言-电子发烧友网站...
  11. gitlab集成openldap认证
  12. 关键对话:如何高效能沟通
  13. vue文件行内样式style提示插件
  14. adblock plus 增加自定义过滤规则,禁止弹出广告网页和隐藏广告块
  15. Ada语言中命令行使用
  16. 成为一名合格软件工程师的7点建议
  17. 浏览器 看不到请求了
  18. 简单的五子棋小游戏(html+css+js)
  19. Unity3D中第三人称视角的镜头跟随和目标锁定
  20. [海森推荐]——上帝掷骰子吗

热门文章

  1. 苹果手机显示没有连接服务器怎么办啊,苹果手机更新连接到服务器出现问题怎么办...
  2. java面试题干货51-95
  3. JasperReport那些事儿(五)——再说表格式报表
  4. Euler formula
  5. cubieboard笔记
  6. Scratch编程(十)扩展模块:视频侦测模块
  7. 在 Flutter 中创建响应式表单
  8. 工业级路由器和家用路由器的区别_工业级路由器和家用路由器有何区别?
  9. 小米怎么快速回到顶部_拆解报告:小米小爱鼠标采用炬芯ATB110X蓝牙物联网方案 -...
  10. tomcat映射本地磁盘路径