[GCJ2017R3]Cooclement
题目大意:
一种数列按照如下方式变化:
新数列第i位等于原数中数字i的出现次数。
变化过程中数列长度不变。
例如数列12的变化过程为12-11-20-01-10。
现在告诉你一个数列x,请求出x可能是有几种数列变化而来的。
思路:
将整个变化过程倒过来,除去自环就是一棵树。
题目就变成了求子树的大小。
显然枚举一个状态所有的前驱(即树上的子结点)会超时,只有25分。
然而如果只是求出一个状态对应的后继(父结点)会很简单。
我们可以枚举出所有的状态,然后求出其后继,最后拓扑排序时DP求出子树大小即可。
对于一些不存在的状态(各位数之和大于长度),我们则没必要遍历,可以特判判掉。
如果一个状态的所有前驱都是不存在的,我们可以直接用组合算出它前驱的数量。
- #include<queue>
- #include<cstdio>
- #include<cctype>
- #include<ext/hash_map>
- int n;
- inline int getint() {
- register char ch;
- n=;
- while(!isdigit(ch=getchar()));
- register int x=ch^'';
- while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^''),n++;
- return x;
- }
- const int N=;
- const int pow[]={,,,,,,,,};
- __gnu_cxx::hash_map<int,int> size[N];
- inline int fact(const int &n) {
- int ret=;
- for(register int i=;i<=n;i++) {
- ret*=i;
- }
- return ret;
- }
- inline int comb(const int &n,const int &m) {
- return fact(n-m);
- }
- __gnu_cxx::hash_map<int,int> deg[N];
- __gnu_cxx::hash_map<int,int> hash_table[N];
- int cnt[N];
- int hash(const int &n,const int &x) {
- if(hash_table[n].count(x)) return hash_table[n][x];
- return hash_table[n][x]=++cnt[n];
- }
- int nxt[N][];
- inline void add_edge(const int &n,const int &u,const int &v) {
- nxt[n][hash(n,u)]=hash(n,v);
- deg[n][hash(n,v)]++;
- }
- void dfs2(const int now,const int &n) {
- int next=,tmp=now;
- while(tmp) {
- next+=tmp%?pow[n-tmp%]:;
- tmp/=;
- }
- if(next==now) {
- size[n][now]--;
- return;
- }
- add_edge(n,now,next);
- }
- void dfs(const int cur,const int &n,const int now,const int sum) {
- if(sum>n) return;
- if(cur==n) {
- if(!sum||size[n].count(hash(n,now))) return;
- int &ans=size[n][hash(n,now)];
- int nn=n,num=now;
- ans=fact(nn);
- while(num) {
- ans/=fact(num%);
- nn-=num%;
- num/=;
- }
- ans/=fact(nn);
- ans++;
- dfs2(now,n);
- return;
- }
- for(int i=;i<=n;i++) {
- dfs(cur+,n,(((now<<)+now)<<)+i,sum+i);
- }
- }
- int main() {
- int T=getint();
- for(register int i=;i<=T;i++) {
- const int x=getint();
- int tmp=x,sum=;
- while(tmp) {
- sum+=tmp%;
- tmp/=;
- }
- if(sum>n) {
- printf("Case #%d: %d\n",i,);
- continue;
- }
- if(size[n].empty()) {
- dfs(,n,,);
- std::queue<int> q;
- for(register int j=;j<=cnt[n];j++) {
- if(!deg[n][j]) {
- q.push(j);
- } else {
- size[n][j]=;
- }
- }
- while(!q.empty()) {
- const int x=q.front();
- q.pop();
- size[n][nxt[n][x]]+=size[n][x];
- if(!--deg[n][nxt[n][x]]) q.push(nxt[n][x]);
- }
- }
- printf("Case #%d: %d\n",i,size[n][hash(n,x)]);
- }
- return ;
- }
[GCJ2017R3]Cooclement的更多相关文章
随机推荐
- Javascript装饰器的妙用
最近新开了一个Node项目,采用TypeScript来开发,在数据库及路由管理方面用了不少的装饰器,发觉这的确是一个好东西.装饰器是一个还处于草案中的特性,目前木有直接支持该语法的环境,但是可以通过 ...
- Hash破解神器:Hashcat的简单使用
Hash破解神器:Hashcat的简单使用 2014-06-10 21:02:42| 分类: 离线密码破解 | 标签:密码字典 rar密码破解 zip密码破解 密码破解 |举报|字号 订阅 ...
- 深入理解C指针----学习笔记
深入理解C指针 第1章 认识指针 理解指针的关键在于理解C程序如何管理内存,指针包含的就是内存地址. 1.1 指针和内存 C程序在编译后,以三种方式使用内存: 1. 静态. ...
- Feather包实现数据框快速读写,你值得拥有
什么是Feather? Feature是一种文件格式,支持R语言和Python的交互式存储,速度更快.目前支持R语言的data.frame和Python pandas 的DataFrame. Feat ...
- flask插件系列之flask_cors跨域请求
前后端分离在开发调试阶段本地的flask测试服务器需要允许跨域访问,简单解决办法有二: 使用flask_cors包 安装 pip install flask_cors 初始化的时候加载配置,这样就可以 ...
- 用户空间与内核空间数据交换的方式(9)------netlink【转】
转自:http://www.cnblogs.com/hoys/archive/2011/04/10/2011722.html Netlink 是一种特殊的 socket,它是 Linux 所特有的,类 ...
- 85.Maximal Rectangle---dp
题目链接:https://leetcode.com/problems/maximal-rectangle/description/ 题目大意:给出一个二维矩阵,计算最大的矩形面积(矩形由1组成).例子 ...
- angular项目中使用Primeng
1.第一步把依赖添加到项目中 npm install primeng --save npm install @angular/animations --save npm install font-aw ...
- nginx 查看当前的连接数
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a,S[a]}' https://www.cnblogs.com/lianzhil ...
- [ python ] 字符串的操作及作业题
字符串的操作方法 capitalize() : 首字母大写 s1 = 'my heart will go on' print(s1.capitalize()) # 首字母大写 # 执行结果: # My ...