Description

Input

从文件 return.in 中读入数据。
输入文件的第1行2个整数n,m,表示时间线的长度和转移的个数。
后面m行每行2个空格隔开的字符串A? ,B? ,描述一组转移。

Output

输出到文件 return.out 中。
输出文件仅1行,1个非负整数,表示答案。

Sample Input

2 3
A B
A C
D D

Sample Output

5
解释:一种最优方案:AA → AB → BA → BC → CB。

Data Constraint

Solution

  • 我们发现其实所谓字符串转换只跟每个字母的个数有关,因为相邻两个字母可以交换。

  • 首先我们要意识到一点:状态数和方案数都不会很多!!!

  • 状态数只有:C4−130+4−1=C333=5456C30+4−14−1=C333=5456C_{30+4-1}^{4-1}=C_{33}^{3}=5456 (用挡板问题解决)。

  • 而答案也不会很多,C1530C3015C_{30}^{15} 也没多大(字母数总和最多才30),并不会爆 long long 。

  • 对于一个状态(设其A-D的个数分别是p1,p2,p3,n−p1−p2−p3p1,p2,p3,n−p1−p2−p3p_1,p_2,p_3,n-p_1-p_2-p_3),

  • 那么它可以转换成的不同排列个数就是:

    Cp1n∗Cp2n−p1∗Cp3n−p1−p2∗Cn−p1−p2−p3n−p1−p2−p3Cnp1∗Cn−p1p2∗Cn−p1−p2p3∗Cn−p1−p2−p3n−p1−p2−p3

    C_n^{p_1}*C_{n-p_1}^{p_2}*C_{n-p_1-p_2}^{p_3}*C_{n-p_1-p_2-p_3}^{n-p_1-p_2-p_3}

  • 我们将这个值设为这个状态的权值。

  • 接着我们枚举那 mmm 中转移方式,将每种状态转移出去并连边(反正状态数又不多)。

  • 做一遍 tarjan 缩环,一个强连通分量的权值就是其中所有点权之和。

  • 这就变成一个点带权的DAG了,我们需要求一条最长路径,

  • 那么直接像拓扑排序一样DP一遍就好了。

  • 时间复杂度约为 O(C333∗m)" role="presentation" style="position: relative;">O(C333∗m)O(C333∗m)O(C_{33}^3*m) 。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=32,M=6000;
struct data
{int x,y;
}edge[M*N];
int n,m,tot,top,num,cnt;
LL ans;
int first[M],nex[M*N],en[M*N];
int a[N<<1][5],b[N<<1][5],c[5],d[5];
int name[N][N][N],q[M],deg[M];
int dfn[M],low[M],st[M],col[M];
bool bz[M];
LL val[M],val1[M],g[N][N],f[M];
char s[N],t[N];
inline int min(int x,int y)
{return x<y?x:y;
}
inline int get(int *pos)
{return name[pos[1]][pos[2]][pos[3]];
}
inline LL calc(int *pos)
{return g[n][pos[1]]*g[n-pos[1]][pos[2]]*g[n-pos[1]-pos[2]][pos[3]];
}
inline void insert(int x,int y)
{nex[++tot]=first[x];first[x]=tot;en[tot]=y;
}
void ergodic(int x,int y)
{if(!y){name[c[1]][c[2]][c[3]]=++tot;return;}if(x>4) return;for(int i=0;i<=y;i++){c[x]=i;ergodic(x+1,y-i);c[x]=0;}
}
void dfs(int x,int y)
{if(!y){int now=get(c);val[now]=calc(c);for(int i=1;i<=m;i++){for(int j=1;j<=4;j++) d[j]=c[j]-a[i][j];bool pd=true;for(int j=1;j<=4;j++)if(d[j]<0){pd=false;break;}if(!pd) continue;for(int j=1;j<=4;j++) d[j]+=b[i][j];int to=get(d);if(now==to) continue;edge[++cnt]=(data){now,to};insert(now,to);}return;}if(x>4) return;for(int i=0;i<=y;i++){c[x]=i;dfs(x+1,y-i);c[x]=0;}
}
void tarjan(int x)
{dfn[x]=low[x]=++tot;bz[st[++top]=x]=true;for(int i=first[x];i;i=nex[i])if(!dfn[en[i]]){tarjan(en[i]);low[x]=min(low[x],low[en[i]]);}elseif(bz[en[i]]) low[x]=min(low[x],dfn[en[i]]);if(dfn[x]==low[x]){num++;do{col[st[top]]=num;bz[st[top--]]=false;}while(st[top+1]^x);}
}
void work()
{int l=0,r=0;for(int i=1;i<=num;i++)if(!deg[i]){q[++r]=i;f[i]=val1[i];if(f[i]>ans) ans=f[i];}while(l<r){int x=q[++l];for(int i=first[x];i;i=nex[i])if(f[x]+val1[en[i]]>f[en[i]]){f[en[i]]=f[x]+val1[en[i]];if(f[en[i]]>ans) ans=f[en[i]];q[++r]=en[i];}}
}
int main()
{freopen("return.in","r",stdin);freopen("return.out","w",stdout);scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){scanf("%s %s",s+1,t+1);int len=strlen(s+1);for(int j=1;j<=len;j++){a[i][s[j]-'A'+1]++;b[i][t[j]-'A'+1]++;}}for(int i=0;i<=n;i++) g[i][0]=1;for(int i=1;i<=n;i++)for(int j=1;j<=i;j++) g[i][j]=g[i-1][j]+g[i-1][j-1];ergodic(1,n);int node=tot;tot=0;dfs(1,n);tot=0;for(int i=1;i<=node;i++)if(!dfn[i]) tarjan(i);for(int i=1;i<=node;i++) val1[col[i]]+=val[i];memset(first,tot=0,sizeof(first));for(int i=1;i<=cnt;i++)if(col[edge[i].x]^col[edge[i].y]){insert(col[edge[i].x],col[edge[i].y]);deg[col[edge[i].y]]++;}work();printf("%lld",ans);return 0;
}

JZOJ 5711. 【北大夏令营2018模拟5.13】时间幻象相关推荐

  1. JZOJ 5710. 【北大夏令营2018模拟5.13】Mex

    Description 在组合游戏中计算状态的 SG 值时,我们常常会遇到 mex 函数.mex(S) 的值为集合 S 中没有出现过的最小自然数.例如,mex({1,2}) = 0.mex({0,1, ...

  2. JZOJ 5709. 【北大夏令营2018模拟5.13】数列

    Description Input 第一行一个整数 n 表示数列长度,第二行 n 个整数 a1 ~an . Output 输出一行一个整数表示答案 . Sample Input 5 50 30 40 ...

  3. 2017广东全国计算机12月,2018年广东考研时间:2017年12月23日至24日

    2018年考研时间已经公布,出国留学考研网为大家提供2018年广东考研时间:2017年12月23日至24日,更多考研资讯请关注我们网站的更新! 2018年广东考研时间:2017年12月23日至24日 ...

  4. Fluent非稳态工况模拟中固定时间步数据输出

    Fluent非稳态工况模拟中固定时间步数据输出 1. 在fluent操作界面中,双击解决方案中的报告定义(report definitions) 2. 弹出的界面中,点击new后选择需要进行报告的数据 ...

  5. 2018河南中考计算机考试,河南中考时间,2018年河南中考时间安排

    2018年河南中考时间:6月25日-6月26日 4月24日,河南省发布了河南省初中学业水平考试实施办法与综合素质评价实施办法,文件中明确指出:初中学业水平考试是学生毕业和升学的基本依据,不是主要依据, ...

  6. JZOJ(中山纪念中学) 2018.02.02【NOIP普及组】模拟赛D组

    本次题目:2018.02.02[NOIP普及组]模拟赛D组 第一题 题目:第一题 公牛数字 题意: 求题目给出两个数字的乘积 分析: 这题明显只是考察学生的高精可我居然没做对,只要多练习几次,即可AC ...

  7. 2019中山纪念中学夏令营-Day9[JZOJ](第六次模拟赛)

    Begin (题目的排序方式:Unkown其实是按心情排的) 异或:(摘自百度百科) 异或(xor)是一个数学运算符.它应用于逻辑运算.异或的数学符号为"⊕",计算机符号为&quo ...

  8. JZOJ 100045. 【NOIP2017提高A组模拟7.13】好数

    Description 我们定义一个非负整数是"好数",当且仅当它符合以下条件之一: 1.这个数是0或1 2.所有小于这个数且与它互质的正整数可以排成一个等差数列例如,8就是一个好 ...

  9. JZOJ(中山纪中)2018.01.21【NOIP普及组】模拟赛D组(第二题)

    1361. [2011.12.31普及模拟]抓捕嫌疑犯(suspect)  (File IO): input:suspect.in output:suspect.out 时间限制: 1000 ms   ...

最新文章

  1. python编程入门电子书下载-Python编程基础如何快速入门?“附电子书下载”
  2. redis中的ziplist
  3. 【强烈推荐】最好理解的LSTM与GRU教程
  4. 【CV秋季划】人脸算法那么多,如何循序渐进地学习好?
  5. appscan无法连接到服务器_对于csgo无法连接到任意服务器解决办法
  6. Jzoj4755 快速荷叶叶变换
  7. 实现离线加域---Windows2008 R2 新功能系列之八
  8. “约见”面试官系列之常见面试题之第九十六篇之active-class是谁的属性(建议收藏)
  9. Apache 和 Tomcat 的 关系
  10. Linux如何动态查看文件信息,怎么查看linux动态链接库文件的版本等其他信息
  11. 循环冗余校验码(计算机组成原理12)
  12. php矢量瓦片,【教你一招】张海平:如何将小范围在线地图切片数据转换为GIS矢量数据?...
  13. Linux修改文件保存时报错E45: 已设定选项 ‘readonly‘ (请加 ! 强制执行)
  14. 羽绒枕头行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  15. 小白兔写话_小白兔写话二年级作文
  16. WATCH ME 2007
  17. c35是什么意思_混凝土标号怎么来的?C30_C25_C35_都是什么意思
  18. python或c++编写一个文件传输工具
  19. Hexo博客Next主题配置加载优化性能提升
  20. 【ivew】ivew 中 render渲染多标签

热门文章

  1. Python:windows程序打包
  2. Markdown:数学公式(4)
  3. CUDA 中 FFT 的使用
  4. 一场惊心动魄的国际黑客入侵保卫战
  5. 一个网站拿下机器学习优质资源!搜索效率提高 50%
  6. FIR数字滤波器设计频率抽样法MATLAB仿真
  7. GPS服务端解析程序编写日记
  8. (转)用ASP.NET向Javascript传递变量 方法1:
  9. IDEA打开html文件时显示错误browser error提示找不到chrome或者别的浏览器
  10. python——文件操作File