CF1225G To Make 1

Posted cjoiershiina-mashiro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1225G To Make 1相关的知识,希望对你有一定的参考价值。

Link
(a_i)总共除过(b_i)次,那么我们要做的就是找到一组(b)使得(sumlimits_{i=0}^na_ik^{-b_i}=1)
显然存在合法的(b)就存在一组合法的合并方案,具体的求解可以dfs。
考虑状压dp,设(f_{s,x})表示存在一组(b)使得(sumlimits_{iin s}a_ik^{-b_i}=x)
转移非常简单就不讲了,注意到复杂度是(O(2^nnk))会爆炸,用bitset优化即可做到(O(frac{2^nnk}{omega}))

#include<queue>
#include<cstdio>
#include<bitset>
#include<utility>
#define se second
const int N=2007,M=65537;
using std::pair;
using pi=pair<int,int>;
int a[16],c[16],low[M],n,k,U,s;
std::bitset<N>f[M];
std::priority_queue<pi>q;
int read(){int x;scanf("%d",&x);return x;}
void dfs(int st,int x)
{
    if(!st) return;
    for(;x*k<=s&&f[st][x*k];x*=k) for(int i=0;i<n;++i) if(st>>i&1) ++c[i];
    for(int i=0;i<n;++i) if(st>>i&1&&x>=a[i]&&f[st^1<<i][x-a[i]]) return dfs(st^1<<i,x-a[i]);
}
int main()
{
    n=read(),k=read(),U=(1<<n)-1,f[0][0]=1;
    for(int i=0;i<n;++i) s+=(a[i]=read()),low[1<<i]=i;
    for(int i=1;i<=U;++i) low[i]=low[i&-i];
    for(int i=1;i<=U;++i)
    {
    for(int j=0;j<n;++j) if(i>>j&1) f[i]|=f[i^1<<j]<<a[j];
    for(int j=s/k;j;--j) if(f[i][j*k]) f[i][j]=1;
    }
    if(!f[U][1]) return puts("NO"),0;
    puts("YES"),dfs(U,1);
    for(int i=0;i<n;++i) q.push({c[i],a[i]});
    for(pi u,v;q.size()>1;)
    {
    u=q.top(),q.pop(),v=q.top(),q.pop(),printf("%d %d
",u.se,v.se),u.se+=v.se;
    while(!(u.se%k)) u.se/=k,--u.first;
    q.push(u);
    }

}

以上是关于CF1225G To Make 1的主要内容,如果未能解决你的问题,请参考以下文章

CF 612C. Replace To Make Regular Bracket Sequence括号匹配

CF1342F Make It Ascending

CF1342F Make It Ascending

[CF1328F] Make k Equal - 贪心

CF1206B Make Product Equal One

1 代码片段1