题目大意:
  一种数列按照如下方式变化:
  新数列第i位等于原数中数字i的出现次数。
  变化过程中数列长度不变。
  例如数列12的变化过程为12-11-20-01-10。
  现在告诉你一个数列x,请求出x可能是有几种数列变化而来的。

思路:
  将整个变化过程倒过来,除去自环就是一棵树。
  题目就变成了求子树的大小。
  显然枚举一个状态所有的前驱(即树上的子结点)会超时,只有25分。
  然而如果只是求出一个状态对应的后继(父结点)会很简单。
  我们可以枚举出所有的状态,然后求出其后继,最后拓扑排序时DP求出子树大小即可。
  对于一些不存在的状态(各位数之和大于长度),我们则没必要遍历,可以特判判掉。
  如果一个状态的所有前驱都是不存在的,我们可以直接用组合算出它前驱的数量。

  1. #include<queue>
  2. #include<cstdio>
  3. #include<cctype>
  4. #include<ext/hash_map>
  5. int n;
  6. inline int getint() {
  7. register char ch;
  8. n=;
  9. while(!isdigit(ch=getchar()));
  10. register int x=ch^'';
  11. while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^''),n++;
  12. return x;
  13. }
  14. const int N=;
  15. const int pow[]={,,,,,,,,};
  16. __gnu_cxx::hash_map<int,int> size[N];
  17. inline int fact(const int &n) {
  18. int ret=;
  19. for(register int i=;i<=n;i++) {
  20. ret*=i;
  21. }
  22. return ret;
  23. }
  24. inline int comb(const int &n,const int &m) {
  25. return fact(n-m);
  26. }
  27. __gnu_cxx::hash_map<int,int> deg[N];
  28. __gnu_cxx::hash_map<int,int> hash_table[N];
  29. int cnt[N];
  30. int hash(const int &n,const int &x) {
  31. if(hash_table[n].count(x)) return hash_table[n][x];
  32. return hash_table[n][x]=++cnt[n];
  33. }
  34. int nxt[N][];
  35. inline void add_edge(const int &n,const int &u,const int &v) {
  36. nxt[n][hash(n,u)]=hash(n,v);
  37. deg[n][hash(n,v)]++;
  38. }
  39. void dfs2(const int now,const int &n) {
  40. int next=,tmp=now;
  41. while(tmp) {
  42. next+=tmp%?pow[n-tmp%]:;
  43. tmp/=;
  44. }
  45. if(next==now) {
  46. size[n][now]--;
  47. return;
  48. }
  49. add_edge(n,now,next);
  50. }
  51. void dfs(const int cur,const int &n,const int now,const int sum) {
  52. if(sum>n) return;
  53. if(cur==n) {
  54. if(!sum||size[n].count(hash(n,now))) return;
  55. int &ans=size[n][hash(n,now)];
  56. int nn=n,num=now;
  57. ans=fact(nn);
  58. while(num) {
  59. ans/=fact(num%);
  60. nn-=num%;
  61. num/=;
  62. }
  63. ans/=fact(nn);
  64. ans++;
  65. dfs2(now,n);
  66. return;
  67. }
  68. for(int i=;i<=n;i++) {
  69. dfs(cur+,n,(((now<<)+now)<<)+i,sum+i);
  70. }
  71. }
  72. int main() {
  73. int T=getint();
  74. for(register int i=;i<=T;i++) {
  75. const int x=getint();
  76. int tmp=x,sum=;
  77. while(tmp) {
  78. sum+=tmp%;
  79. tmp/=;
  80. }
  81. if(sum>n) {
  82. printf("Case #%d: %d\n",i,);
  83. continue;
  84. }
  85. if(size[n].empty()) {
  86. dfs(,n,,);
  87. std::queue<int> q;
  88. for(register int j=;j<=cnt[n];j++) {
  89. if(!deg[n][j]) {
  90. q.push(j);
  91. } else {
  92. size[n][j]=;
  93. }
  94. }
  95. while(!q.empty()) {
  96. const int x=q.front();
  97. q.pop();
  98. size[n][nxt[n][x]]+=size[n][x];
  99. if(!--deg[n][nxt[n][x]]) q.push(nxt[n][x]);
  100. }
  101. }
  102. printf("Case #%d: %d\n",i,size[n][hash(n,x)]);
  103. }
  104. return ;
  105. }

[GCJ2017R3]Cooclement的更多相关文章

随机推荐

  1. Javascript装饰器的妙用

    最近新开了一个Node项目,采用TypeScript来开发,在数据库及路由管理方面用了不少的装饰器,发觉这的确是一个好东西.装饰器是一个还处于草案中的特性,目前木有直接支持该语法的环境,但是可以通过 ...

  2. Hash破解神器:Hashcat的简单使用

    Hash破解神器:Hashcat的简单使用 2014-06-10 21:02:42|  分类: 离线密码破解 |  标签:密码字典  rar密码破解  zip密码破解  密码破解  |举报|字号 订阅 ...

  3. 深入理解C指针----学习笔记

      深入理解C指针     第1章 认识指针   理解指针的关键在于理解C程序如何管理内存,指针包含的就是内存地址.     1.1 指针和内存   C程序在编译后,以三种方式使用内存: 1. 静态. ...

  4. Feather包实现数据框快速读写,你值得拥有

    什么是Feather? Feature是一种文件格式,支持R语言和Python的交互式存储,速度更快.目前支持R语言的data.frame和Python pandas 的DataFrame. Feat ...

  5. flask插件系列之flask_cors跨域请求

    前后端分离在开发调试阶段本地的flask测试服务器需要允许跨域访问,简单解决办法有二: 使用flask_cors包 安装 pip install flask_cors 初始化的时候加载配置,这样就可以 ...

  6. 用户空间与内核空间数据交换的方式(9)------netlink【转】

    转自:http://www.cnblogs.com/hoys/archive/2011/04/10/2011722.html Netlink 是一种特殊的 socket,它是 Linux 所特有的,类 ...

  7. 85.Maximal Rectangle---dp

    题目链接:https://leetcode.com/problems/maximal-rectangle/description/ 题目大意:给出一个二维矩阵,计算最大的矩形面积(矩形由1组成).例子 ...

  8. angular项目中使用Primeng

    1.第一步把依赖添加到项目中 npm install primeng --save npm install @angular/animations --save npm install font-aw ...

  9. nginx 查看当前的连接数

    netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a,S[a]}' https://www.cnblogs.com/lianzhil ...

  10. [ python ] 字符串的操作及作业题

    字符串的操作方法 capitalize() : 首字母大写 s1 = 'my heart will go on' print(s1.capitalize()) # 首字母大写 # 执行结果: # My ...