Codeforces 题目传送门 & 洛谷题目传送门

还是做题做太少了啊……碰到这种题一点感觉都没有……

首先我们来证明一件事情,那就是存在一种合并方式 \(\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+找性质)的更多相关文章

  1. Codeforces Gym 100015F Fighting for Triangles 状压DP

    Fighting for Triangles 题目连接: http://codeforces.com/gym/100015/attachments Description Andy and Ralph ...

  2. codeforces 342D Xenia and Dominoes(状压dp+容斥)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud D. Xenia and Dominoes Xenia likes puzzles ...

  3. Codeforces 375C - Circling Round Treasures(状压 dp+最短路转移)

    题面传送门 注意到这题中宝藏 \(+\) 炸弹个数最多只有 \(8\) 个,故考虑状压,设 \(dp[x][y][S]\) 表示当前坐标为 \((x,y)\),有且仅有 \(S\) 当中的物品被包围在 ...

  4. Codeforces Beta Round #16 E. Fish (状压dp)(概率dp)

    Codeforces Beta Round #16 (Div. 2 Only) E. Fish 题目链接:## 点击打开链接 题意: 有 \(n\) 条鱼,每两条鱼相遇都会有其中一只吃掉对方,现在给你 ...

  5. codeforces gym #101161H - Witcher Potion(状压DP)

    题目链接: http://codeforces.com/gym/101161/attachments 题意: 总共有n瓶药可供选择 每瓶药可以增加$e_i$点体力,和$p_i$点毒性 每分钟消耗1点毒 ...

  6. Codeforces 580D Kefa and Dishes(状压DP)

    题目大概说要吃掉n个食物里m个,吃掉各个食物都会得到一定的满意度,有些食物如果在某些食物之后吃还会增加满意度,问怎么吃满意度最高. dp[S][i]表示已经吃掉的食物集合是S且刚吃的是第i个食物的最大 ...

  7. CodeForces 385 D.Bear and Floodlight 状压DP

    枚举灯的所有可能状态(亮或者不亮)(1<<20)最多可能的情况有1048576种 dp[i]表示 i 状态时灯所能照射到的最远距离(i 的二进制中如果第j位为0,则表示第j个灯不亮,否则就 ...

  8. Codeforces 599E Sandy and Nuts(状压DP)

    题目链接 Sandy and Nuts 题意大概就是给出限制条件求出在该限制条件下树的种数. #include <bits/stdc++.h> using namespace std; # ...

  9. 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 ...

随机推荐

  1. Linux常用命令查看文件、别名、切换目录、创建目录、查看当前目录

    一.创建条件(使用liunx常用命令): 1.查看阿里云的环境是否搭建完成 首先快捷键 win+R 输入cmd 回车,打开命令提示符输入命令 ssh,回车.  2.登录阿里云账户 输入命令格式:ssh ...

  2. Scrum Meeting 0501

    零.说明 日期:2021-5-1 任务:简要汇报两日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 两日内已完成的任务 后两日计划完成的任务 qsy PM&前端 整装待发,准备冲刺 ...

  3. [no code][scrum meeting] Alpha 2

    项目 内容 会议时间 2020-04-07 会议主题 功能规格说明书review 会议时长 30min 参会人员 OCR组(肖思炀,赵涛)和产品经理 $( "#cnblogs_post_bo ...

  4. webpack基础以及webpack中babel的配置

    webpack 安装 npm 初始化,控制台输入 npm init -y webpack 安装 npm i webpack webpack-cli -D 新建 webpack.config.js co ...

  5. Noip模拟13 2021.7.13:再刚题,就剁手&&生日祭

    T1 工业题 这波行列看反就非常尴尬.....口糊出所有正解想到的唯独行列看反全盘炸列(因为和T1斗智斗勇两个半小时...) 这题就是肯定是个O(n+m)的,那就往哪里想,a,b和前面的系数分开求,前 ...

  6. 震惊,hzoi的考试竟然折磨简单,活到爆!

    众所周知,hzoi的考试题非常"简单",那么究竟有多简单呢?最近,一位外国小哥开发出了hzoi的考试竟然折磨简单,活到爆!的方法,这究竟是怎么一回事呢?快和小编一起来看看吧- 满分 ...

  7. JAVA笔记14__多线程共享数据(同步)/ 线程死锁 / 生产者与消费者应用案例 / 线程池

    /** * 多线程共享数据 * 线程同步:多个线程在同一个时间段只能有一个线程执行其指定代码,其他线程要等待此线程完成之后才可以继续执行. * 多线程共享数据的安全问题,使用同步解决. * 线程同步两 ...

  8. PWN环境搭建

    目录 PWN环境搭建 需要的工具或系统 安装PWN工具 pwntools (CTF库.漏洞利用库) pwngdb(GDB插件) checksec(查保护) ROPGadget(二进制文件查找工具) o ...

  9. Spring Cloud Alibaba环境搭建

    前言:Spring Cloud Alibaba是目前主流的分布式微服务架构,本文主要讲解了在IDEA中如何搭建Spring Cloud Alibaba环境,以及介绍Spring Cloud Aliba ...

  10. Node.js躬行记(14)——压力测试

    公司有个匿名聊天的常规H5界面,运营向做一次 50W 的推送,为了能配合她的计划,需要对该界面做一次压力测试. 一.JMeter 压测工具选择了JMeter,这是Apache的一个项目,它是用Java ...