CF1290F Making Shapes——数位背包DP
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∑cixi=xj<0∑cj(−xj)yi>0∑ciyi=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∑cixi≤m且yi>0∑ciyi≤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>0cixi 的前 w−1w-1w−1 位是否 ≤m\le m≤m,
qqq:∑yi>0ciyi\sum_{y_i>0}c_iy_i∑yi>0ciyi 的前 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>0cixi=∑xj<0cj(−xj),∑yi>0ciyi=∑yj<0cj(−yj)\sum_{y_i>0}c_iy_i=\sum_{y_j<0}c_j(-y_j)∑yi>0ciyi=∑yj<0cj(−yj),且保证最高位没有进位,ppp 和 qqq 都为1。
最后要减去系数全为0的1种情况,因为要求凸包面积非0。
总复杂度为 O(2n(4n)4logm)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相关推荐
- 【LibreOJ】#6395. 「THUPC2018」城市地铁规划 / City 背包DP+Prufer序
[题目]#6395. 「THUPC2018」城市地铁规划 / City [题意]给定n个点要求构造一棵树,每个点的价值是一个关于点度的k次多项式,系数均为给定的\(a_0,...a_k\),求最大价值 ...
- 背包dp的核心思想(动态规划)
背包dp 突然发现我一直没有真正理解背包,真正的背包应该是用空间换时间的一种dp方法,本质上就是n个物品选或不选,理论上有2n2^n2n种可能结果,但是背包利用的就是值域很小这一特点来重叠子结构,所以 ...
- Codeforces 864E Fire(背包DP)
背包DP,决策的时候记一下 jc[i][j]=1 表示第i个物品容量为j的时候要选,输出方案的时候倒推就好了 #include<iostream> #include<cstdlib& ...
- 【bzoj4007】[JLOI2015]战争调度 暴力+树形背包dp
题目描述 给你一棵 $n$ 层的完全二叉树,每个节点可以染黑白两种颜色.对于每个叶子节点及其某个祖先节点,如果它们均为黑色则有一个贡献值,如果均为白色则有另一个贡献值.要求黑色的叶子节点数目不超过 $ ...
- HDU 1011 Starship Troopers 树形+背包dp
http://acm.hdu.edu.cn/showproblem.php?pid=1011 题意:每个节点有两个值bug和brain,当清扫该节点的所有bug时就得到brain值,只有当父节点被 ...
- 【bzoj1222】[HNOI2001]产品加工 背包dp
题目描述 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机器共同进行加工 ...
- 【bzoj4753】[Jsoi2016]最佳团体 分数规划+树形背包dp
题目描述 JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一位编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY自己看上的.为了 ...
- 【bzoj5072】[Lydsy十月月赛]小A的树 树形背包dp
题目描述 给出一棵n个点的树,每个点有黑白两种颜色.q次询问,每次询问给出x和y,问能否选出一个x个点的联通子图,使得其中黑点数目为y. 输入 第一行一个正整数 T 表示数据组数. 对于每一组数据,第 ...
- 【背包DP练习】洛谷 P5020货币系统 P1757通天之分组背包 P1064[NOIP2006 提高组]金明的预算方案 P5322 [BJOI2019]排兵布阵
洛谷 P5020货币系统 https://www.luogu.com.cn/problem/P5020 思路是把货币从小到大排序,然后按顺序依次完全背包dp,每次dp检查i-1种面值的货币能不能凑出第 ...
- hdu 5234 Happy birthday 背包 dp
Happy birthday Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...
最新文章
- [洛谷P2742]【模板】二维凸包([USACO5.1]圈奶牛Fencing the Cows)
- ML之NBLoR:利用NB(朴素贝叶斯)、LoR(逻辑斯蒂回归)算法(+TfidfVectorizer)对Rotten Tomatoes影评数据集进行文本情感分析—五分类预测
- Android开发之关于transformDexArchiveWithExternalLibsDexMergerForDebug java.lang.OutOfMemoryError问题的参考解决方案
- 执行work count程序报错Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster
- 智能控制在计算机领域的应用,智能控制的主要应用领域
- 【测试】软件测试之测试用例的设计方法
- AI+IoT行业“飞轮效应”凸显,全球云服务能力将发挥关键作用
- 子在川上曰:nginx的安装和配置、node服务器的配置、mongdb的安装、pm2进行项目动态管理
- UDP协议全面实验分析详解
- 计算机组成原理DMA的全称,直接存贮器存取(DMA) -计算机组成原理与汇编语言-电子发烧友网站...
- gitlab集成openldap认证
- 关键对话:如何高效能沟通
- vue文件行内样式style提示插件
- adblock plus 增加自定义过滤规则,禁止弹出广告网页和隐藏广告块
- Ada语言中命令行使用
- 成为一名合格软件工程师的7点建议
- 浏览器 看不到请求了
- 简单的五子棋小游戏(html+css+js)
- Unity3D中第三人称视角的镜头跟随和目标锁定
- [海森推荐]——上帝掷骰子吗
热门文章
- 苹果手机显示没有连接服务器怎么办啊,苹果手机更新连接到服务器出现问题怎么办...
- java面试题干货51-95
- JasperReport那些事儿(五)——再说表格式报表
- Euler formula
- cubieboard笔记
- Scratch编程(十)扩展模块:视频侦测模块
- 在 Flutter 中创建响应式表单
- 工业级路由器和家用路由器的区别_工业级路由器和家用路由器有何区别?
- 小米怎么快速回到顶部_拆解报告:小米小爱鼠标采用炬芯ATB110X蓝牙物联网方案 -...
- tomcat映射本地磁盘路径