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

神奇的强迫症效应,一场只要 AC 了 ABDEF,就一定会把 C 补掉(

感觉这个 C 难度比 D 难度高啊……

首先考虑对问题进行初步转化。显然对于 \(s_i=s_j,t_i=t_j\)​ 的 \((i,j)\)​,我们肯定会将它们放在一起操作,这启发我们将所有 \((s_i,t_i)\)​ 看作一个二元组,那么如果我们把“每一步将字符 \(x\) 变为 \(y\)”这样的操作视作一条从 \(x\) 连向 \(y\),权值为当前是第几次操作。那么一个连边方式合法,当且仅当对于所有二元组 \((s,t)\) 都存在一条 \(s\to t\) 的路径,满足其经过的所有边的权值单调递增。

考虑怎样解决这个问题,首先注意到 \(39\)​​​ 次操作一定是可行的,具体来说就 \(’a’\to’b’\to’c’\to\cdots\to’t’\to’a’\to\cdots’t’\)​​​ 连两个环,这样一定能保证对于所有 \((x,y)\)​​ 都存在符合要求的路径,不过注意到我们并不一定要所有 \((x,y)\)​​ 之间都存在符合要求的路径,因此考虑从这个角度入手减少操作次数。这里直接给出结论:如果我们设 \(n=20\)​​ 表示图中的点数,对于所有二元组 \(s\to t\)​​ 我们再建一张图 \(G\)​​,并设 \(S\)​​ 表示满足 \(S\subseteq G\)​​,\(S\)​​ 为 DAG 且 \(S\)​​ 包含的点数最多的导出子图,\(c\)​ 表示 \(G\)​ 中弱连通块的个数,那么 \(res=2n-S\)​ 中点的个数 \(-c\)​。​

证明:首先我们来说明我们能达到这张图,我们考察 \(G\) 中每一个弱连通块,显然它有一部分点是包含在 \(S\) 当中的对吧,对于这部分点我们将它们按拓扑序编号 \(1,2,3,\cdots,k\),其中 \(k\) 表示该连通块中包含在 \(S\) 中的点数,对于剩余的点我们随意编号 \(k+1,k+2,\cdots,m\),那么我们考虑这样连边:\(k\to k+1\to k+2\to\cdots\to m\to 1\to 2\to\cdots\to k\to k+1\to k+2\to\cdots m\),这样总边数显然是 \(2m-k-1\),不难发现这样一来,该连通块中只有 DAG 中拓扑序从后往前的二元组无法到达,而由于这是一个 DAG,因此这样的点之间没有边,符合要求,把它们的贡献累加起来就是 \(2n-S\) 中点的个数 \(-c\)。

接下来来说明这就是本题操作次数的下界。我们不妨想象这样一个在一个初始没有边的图中加边的过程,每加入一条边有两种可能,要么沟通了原本不在同一个弱连通块中的两点,由最终得到的图中恰有 \(c\)​​​ 个连通块可知这样的边至少有 \(n-c\)​​​ 条,要么连接了两个原本就在同一连通块中的边,对于这样的边我们维护一个 \(T\)​​​ 表示当前无法沿着一个合法的路径到达本身的点集,那么显然初始 \(T=\{1,2,3\cdots,n\}\)​​​,而当我们加入 \((x,y)\)​​​ 这条边时,最多使 \(y\)​​​ 这个点能够到达本身,即 \(T\)​​​ 的大小最多减 \(1\)​​​,因此如果最终 \(|T|=x\)​​​,那么操作次数 \(\ge n-c+n-x\)​​​,又显然最终 \(T\)​​​ 中的点必须形成一个 DAG,否则其中必然存在圈 \(x_1\to x_2\to\cdots\to x_k\to x_1\)​​,由于这些边必须可达,因此可以推出 \(x_1\)​​ 可以到达 \(x_1\)​​,与 \(T\)​​ 的定义矛盾。因此最终 \(x\le\)​​ 上文中 \(S\)​​ 的点数,也就证明了答案的下界。据说这方法有个名字叫势能法?反正总之很神仙就对了(

有了这个性质之后题目就很容易了。\(n,c\) 都很容易求得。至于怎样求 \(S\) 的大小……注意到这题最多涉及到 \(20\) 个字母,即点数最多 \(20\),一脸状压,直接枚举 \(S\) 的点集并 check 是 \(2^{20}20^2\) 的,不知道能不能通过。考虑加点《小优化》,我们设 \(dp_S\) 表示 \(S\) 的导出子图是否是一个 DAG,那么我们考虑每次增加一个点 \(x\) 作为 DAG 中出度为 \(0\) 的点并检验这个点连出去的边中,是否有边指向 \(S\) 中的点,如果有那么 \(dp_{S\cup\{x\}}=0\),否则 \(dp_{S\cup\{x\}}=1\),这样是 \(2^{20}·20\) 的,可以通过。

const int ALPHA=20;
const int MAXN=1e5;
const int MAXP=1048576;
int n,f[ALPHA+2],fr[ALPHA+2];
char s[MAXN+5],t[MAXN+5];
bool dp[MAXP+5];
void clear(){memset(f,-1,sizeof(f));memset(fr,0,sizeof(fr));memset(dp,0,sizeof(dp));}
int find(int x){return (!~f[x])?x:f[x]=find(f[x]);}
void merge(int x,int y){x=find(x);y=find(y);if(x^y) f[x]=y;}
void solve(){
scanf("%d%s%s",&n,s+1,t+1);clear();
for(int i=1;i<=n;i++){
int x=s[i]-'a',y=t[i]-'a';
fr[x]|=(1<<y);merge(x,y);
} int res=ALPHA<<1,mx=0;
for(int i=0;i<ALPHA;i++) if(find(i)==i) res--;
dp[0]=1;for(int i=0;i<MAXP;i++) if(dp[i]){
chkmax(mx,__builtin_popcount(i));
for(int j=0;j<ALPHA;j++) if(~i>>j&1){
if((fr[j]&i)==0) dp[i|(1<<j)]=1;
}
} printf("%d\n",res-mx);
}
int main(){
int qu;scanf("%d",&qu);
while(qu--) solve();
return 0;
}

Codeforces 1383C - String Transformation 2(找性质+状压 dp)的更多相关文章

  1. 没有找零 状压dp

    没有找零 状压dp 约翰到商场购物,他的钱包里有K(1 <= K <= 16)个硬币,面值的范围是1..100,000,000.约翰想按顺序买 N个物品(1 <= N <= 1 ...

  2. Codeforces 1225G - To Make 1(bitset+状压 dp+找性质)

    Codeforces 题目传送门 & 洛谷题目传送门 还是做题做太少了啊--碰到这种题一点感觉都没有-- 首先我们来证明一件事情,那就是存在一种合并方式 \(\Leftrightarrow\) ...

  3. Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP

    Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...

  4. Educational Codeforces Round 13 E. Another Sith Tournament 状压dp

    E. Another Sith Tournament 题目连接: http://www.codeforces.com/contest/678/problem/E Description The rul ...

  5. [BZOJ3312][USACO]不找零(状压DP)

    Description 约翰带着 N 头奶牛在超市买东西,现在他们正在排队付钱,排在第 i 个位置的奶牛需要支付 Ci元.今天说好所有东西都是约翰请客的,但直到付账的时候,约翰才意识到自己没带钱,身上 ...

  6. CF1103D Codeforces Round #534 (Div. 1) Professional layer 状压 DP

    题目传送门 https://codeforces.com/contest/1103/problem/D 题解 失去信仰的低水平选手的看题解的心路历程. 一开始看题目以为是选出一些数,每个数可以除掉一个 ...

  7. FZU 2093 找兔子 状压DP

    题目链接:找兔子 n的范围是[1, 15],可以用0 到 (1<<n)-1 的数表示全部状态,用dp[i] = t表示到达状态i的最少时间是t,对于每个点,如果它能到达的所有点在t秒时都已 ...

  8. Codeforces 279D The Minimum Number of Variables 状压dp

    The Minimum Number of Variables 我们定义dp[ i ][ mask ]表示是否存在 处理完前 i 个a, b中存者 a存在的状态是mask 的情况. 然后用sosdp处 ...

  9. codeforces#580 D. Kefa and Dishes(状压dp)

    题意:有n个菜,每个菜有个兴奋值,并且如果吃饭第i个菜立即吃第j个菜,那么兴奋值加ma[i][j],求吃m个菜的最大兴奋值,(n<=18) 分析:定义dp[status][last],statu ...

随机推荐

  1. LeetCode:“剑指 Offer”

    LeetCode:"剑指 Offer" 刷题小菜鸡,花了几天时间做了一遍 LeetCode 上给出的 "剑指 Offer" 在此做一下记录 LeetCode主页 ...

  2. [no code][scrum meeting] Beta 12

    $( "#cnblogs_post_body" ).catalog() 例会时间:5月27日11:30,主持者:乔玺华 一.工作汇报 人员 昨日完成任务 明日要完成的任务 乔玺华 ...

  3. 【二食堂】Beta - Scrum Meeting 5

    Scrum Meeting 5 例会时间:5.18 18:30~18:50 进度情况 组员 当前进度 今日任务 李健 1. 划词功能已经实现,继续开发,完善文本区域交互,调用API issue 1. ...

  4. Java 将Word保存为WPS和WPT格式

    本文通过Java示例展示将Word文档(如.doc/.docx)保存为WPS和WPT格式的方法. 程序环境配置 IntelliJ IDEA 2018(jdk 1.8.0) Word Jar包:Spir ...

  5. 【SDOI2014】数数(补)

    见 AC自动机(补坑了) [SDOI2014] 数数 简要题意:  我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为子串.例如当S={22,333,0233}时 ...

  6. IDA*、剪枝、较难搜索、扫描——DNA sequence HDU - 1560

    万恶之源 翻译 题意就是给出N个DNA序列,要求出一个包含这n个序列的最短序列是多长 这是一道搜索题,为什么呢?从样例可以感受到,我们应该从左往右"扫描",从n个DNA序列中取出某 ...

  7. 平衡二叉树检查 牛客网 程序员面试金典 C++ Python

    平衡二叉树检查 牛客网 程序员面试金典 C++ Python 题目描述 实现一个函数,检查二叉树是否平衡,平衡的定义如下,对于树中的任意一个结点,其两颗子树的高度差不超过1. 给定指向树根结点的指针T ...

  8. AGC036 A-Triangle | 构造

    题目链接 题意: 给出一个数$S(1\leqslant S \leqslant 10^{18})$. 要求在平面直角坐标系中找到三个点$(X_1,Y_1),(X_2,Y_2),(X_3,Y_3)$,满 ...

  9. 前端面试手写代码——JS函数柯里化

    目录 1 什么是函数柯里化 2 柯里化的作用和特点 2.1 参数复用 2.2 提前返回 2.3 延迟执行 3 封装通用柯里化工具函数 4 总结和补充 1 什么是函数柯里化 在计算机科学中,柯里化(Cu ...

  10. iscsi基本命令

    磁阵操作命令 根据磁阵端配置的业务地址(targetIP)和端口(3260),命令iscsiadm -m discovery -t sendtargets -p targetIP:port(3260) ...