Codeforces 1225G - To Make 1(bitset+状压 dp+找性质)
还是做题做太少了啊……碰到这种题一点感觉都没有……
首先我们来证明一件事情,那就是存在一种合并方式 \(\Leftrightarrow\) \(\exist b_i\in\mathbb{Z}^+,\sum\limits_{i=1}^na_ik^{-b_i}=1\)
考虑充分性,倘若我们已经知道了 \(b_1,b_2,\dots,b_n\) 的值怎样构造合并的序列,考虑 \(B=\max\limits_{i=1}^nb_i\),这里有一个结论,那就是 \(b_i=B\) 的 \(i\) 至少有两个,否则,等式两边同时乘 \(k^B\) 可得 \(\sum\limits_{i=1}^na_ik^{B-b_i}=k^B\),而右边 \(k\mid k^B\),左边 \(\forall b_i<B,k\mid k^{B-b_i}\),又 \(k\nmid a_i\),故若满足 \(b_i=B\) 的 \(i\) 只有一个,那么 \(\sum\limits_{i=1}^na_ik^{B-b_i}\equiv a_i\not\equiv 0\pmod{k}\),矛盾。
此时假设 \(b_i=b_j=B\),那么我们合并 \(a_i,a_j\) 即可,假设 \(a_i+a_j=A\times k^{\alpha}\),那么 \(a_i,a_j\) 合并后就会变成 \(A\),而合并之后满足 \(\sum\limits_{i}a_ik^{-b_i}\) 的 \(b_i\) 依旧存在,因为 \(\dfrac{a_i}{k^B}+\dfrac{a_j}{k^B}=\dfrac{a_i+a_j}{k^B}=\dfrac{A}{k^{B-\alpha}}\),此时只需令其它 \(a_i\) 的 \(b_i\) 保持不变,新合并出的元素的 \(b\) 值为 \(B-\alpha\) 即可。如此合并 \(n-1\) 轮必定会得到一个数,这个数就是 \(1\)。
接下来考虑必要性,证明必要性等价于证明如果存在合法的合并方案,那么一定可以构造出合法的 \(b\) 序列。显然对于任意一种合并的局面,序列中每个数都可以看作原序列中一些数合并的结果,我们对于第 \(i\) 个数记这个集合为 \(S_i\),显然初始 \(S_i=\{i\}\)。我们构造初始 \(b_i=0\)。我们假设当前步合并了 \(a'_i,a'_j\) 两个元素,并且 \(a'_i+a'_j=A\times k^{\alpha}\),那么我们令 \(S_i,S_j\) 中所有元素的 \(b\) 值都增加 \(\alpha\)。这样构造出来有一个结论,那就是对于任意一个局面中的任意一个数 \(a'_i\),都有 \(a'_i=\sum\limits_{j\in S_i}a_jk^{-b_j}\),其中 \(a_j\) 为初始序列中下标为 \(j\) 的元素的值。这个结论显然可以归纳证明,对于初始局面显然满足,当我们合并两个数 \(a'_i,a'_j\) 时,\(A=\dfrac{a'_i+a'_j}{k^{\alpha}}=\dfrac{\sum\limits_{p\in S_i}a_pk^{-b'_p}+\sum\limits_{p\in S_j}a_pk^{-b'_p}}{k^{\alpha}}=\sum\limits_{p\in S_i}a_pk^{-b'_p-\alpha}+\sum\limits_{p\in S_j}a_pk^{-b'_p-\alpha}=\sum\limits_{p\in S_i\lor p\in S_j}a_pk^{-b_p}\),得证。又因为最终合并出来的数为 \(1\),最后合并出来的数对应的 \(S\) 显然为全集,故 \(\sum\limits_{i=1}^na_ik^{-b_i}=1\)。
这样就可以 \(dp\),此题 \(n\) 数据范围很小,故考虑状压 \(dp\),\(dp_{S,x}\) 表示考虑了 \(S\) 中的数,这些数和为 \(x\) 是否可行。转移比较容易,如果不能一眼看出转移的建议康下这个题。转移到 \(dp_{S,x}\) 可以新加入一个元素,即 \(dp_{S,x}|=dp_{S-\{u\},x-a_u}\),或者将序列中所有数都除以 \(k\),即 \(dp_{S,x}|=dp_{S,xk}\),复杂度 \(n2^n\sum a_i\approx 2\times 10^9\),会 TLE。不过注意到 \(dp\) 的每一个元素都是一个 bool
类型的数,故考虑 bitset
优化,复杂度可降到 \(\dfrac{n2^n\sum a_i}{\omega}+2^n\sum a_i\) 即可通过此题。
至于输出方案,就暴力找出 \(b\) 序列然后按照上述方式合并即可。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=16;
const int MAXV=2000;
const int MAXP=1<<MAXN;
int n,k,a[MAXN+5],b[MAXN+5],sum=0;
bitset<MAXV+5> bt[MAXP+5];
void getstate(int st,int x){
// printf("%d %d\n",st,x);
if(!st) return;
if(x*k<=sum&&bt[st][x*k]){
for(int i=1;i<=n;i++) if(st>>i-1&1) b[i]++;
getstate(st,x*k);return;
}
for(int i=1;i<=n;i++) if(st>>i-1&1){
if(x-a[i]>=0&&bt[st^1<<i-1][x-a[i]]){
getstate(st^1<<i-1,x-a[i]);return;
}
}
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i];
bt[0][0]=1;
for(int i=0;i<(1<<n);i++){
for(int j=1;j<=n;j++) if(i>>j-1&1) bt[i]|=bt[i^1<<j-1]<<a[j];
for(int j=sum/k;j;j--) if(bt[i][j*k]) bt[i][j]=1;
}
if(!bt[(1<<n)-1][1]) puts("NO");
else{
puts("YES");getstate((1<<n)-1,1);
priority_queue<pii> q;
for(int i=1;i<=n;i++) q.push(mp(b[i],a[i]));
while(q.size()>1){
pii p1=q.top();q.pop();
pii p2=q.top();q.pop();
printf("%d %d\n",p1.se,p2.se);
p1.se+=p2.se;
while(p1.se%k==0) p1.se/=k,p1.fi--;
q.push(p1);
}
}
return 0;
}
Codeforces 1225G - To Make 1(bitset+状压 dp+找性质)的更多相关文章
- Codeforces Gym 100015F Fighting for Triangles 状压DP
Fighting for Triangles 题目连接: http://codeforces.com/gym/100015/attachments Description Andy and Ralph ...
- codeforces 342D Xenia and Dominoes(状压dp+容斥)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud D. Xenia and Dominoes Xenia likes puzzles ...
- Codeforces 375C - Circling Round Treasures(状压 dp+最短路转移)
题面传送门 注意到这题中宝藏 \(+\) 炸弹个数最多只有 \(8\) 个,故考虑状压,设 \(dp[x][y][S]\) 表示当前坐标为 \((x,y)\),有且仅有 \(S\) 当中的物品被包围在 ...
- Codeforces Beta Round #16 E. Fish (状压dp)(概率dp)
Codeforces Beta Round #16 (Div. 2 Only) E. Fish 题目链接:## 点击打开链接 题意: 有 \(n\) 条鱼,每两条鱼相遇都会有其中一只吃掉对方,现在给你 ...
- codeforces gym #101161H - Witcher Potion(状压DP)
题目链接: http://codeforces.com/gym/101161/attachments 题意: 总共有n瓶药可供选择 每瓶药可以增加$e_i$点体力,和$p_i$点毒性 每分钟消耗1点毒 ...
- Codeforces 580D Kefa and Dishes(状压DP)
题目大概说要吃掉n个食物里m个,吃掉各个食物都会得到一定的满意度,有些食物如果在某些食物之后吃还会增加满意度,问怎么吃满意度最高. dp[S][i]表示已经吃掉的食物集合是S且刚吃的是第i个食物的最大 ...
- CodeForces 385 D.Bear and Floodlight 状压DP
枚举灯的所有可能状态(亮或者不亮)(1<<20)最多可能的情况有1048576种 dp[i]表示 i 状态时灯所能照射到的最远距离(i 的二进制中如果第j位为0,则表示第j个灯不亮,否则就 ...
- Codeforces 599E Sandy and Nuts(状压DP)
题目链接 Sandy and Nuts 题意大概就是给出限制条件求出在该限制条件下树的种数. #include <bits/stdc++.h> using namespace std; # ...
- Codeforces Beta Round #8 C. Looking for Order 状压dp
题目链接: http://codeforces.com/problemset/problem/8/C C. Looking for Order time limit per test:4 second ...
随机推荐
- [对对子队]Scrum Meeting 博客汇总
对对子队 博客目录 一.Scrum Meeting 1. Alpha Scrum Meeting 1(会议记录4.10) Scrum Meeting 2(会议记录4.11) Scrum Meeting ...
- [技术博客]Unity3d 动画控制
在制作游戏时,导入的箱子模型本身自带动画.然而,它的动画是一个从打开到关闭的完整过程,并且没有给出控制打开关闭的方法. 最直接的想法是对该动画进行拆分,再封装成不同的动画状态,但是不巧的是,这个动画被 ...
- [技术博客] 敏捷软工——JavaScript踩坑记
[技术博客] 敏捷软工--JavaScript踩坑记 一.一个令人影响深刻的坑 1.脚本语言的面向对象 面向对象特性是现代编程语言的基本特性,JavaScript中当然集成了面向对象特性.但是Java ...
- 【二食堂】Alpha - 事后分析
事后分析 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? Alpha阶段要解决的问题是:根据用户标注的信息完成知识图谱的生成渲染.要解决的问题定义得比较 ...
- Noip模拟5 2021.6.7
T1 string(线段树优化) 看到数据范围就必须要想到优化,那么如何把26×M∗N 的复杂度降低呢?? 用到那个我们最不想打的数据结构--线段树...... 然而,这个线段树与往常不同,他只需要用 ...
- 高斯消元de小板几
感觉就是模拟解方程,还比手动解方程笨一些.... 但是大数据的话,他毕竟比我解得快多了.... 1 inline int Gauss(int n){ 2 int cnt=1;//真实到达的行列式行数 ...
- 使用 ASP.NET Core 3.1 的微服务开发指南
使用 ASP.NET Core 3.1 的微服务 – 终极详细指南 https://procodeguide.com/programming/microservices-asp-net-core/ A ...
- hdu 5179 beautiful number(构造,,,,)
题意: 一个如果称作是漂亮数,当且仅当满足: 每一位上的数字是[1,9],从高到时低数字大小降序,且有di%dj=0(i<j) 例:931 给一个区间[L,R],问这个区间里有多少个漂亮数. 1 ...
- 从0到1搭建自己的组件(vue-code-view)库(上)
0x00 前言 本文将从结构.功能等方面讲解下项目 vue-code-view 的搭建过程,您可以了解以下内容: 使用 vue cli 4从0搭建一个组件库及细致配置信息. 项目的多环境构建配置. 项 ...
- DeWeb 与 Unigui的区别
DeWeb 与 Unigui 相同: 都是采用Delphi开发网页的平台 不同: 1 DeWeb不需要安装控件, 而Unigui需要安装自己的控件 2 DeWeb无需要学习HTML/CSS/JavaS ...