大意: 给定一棵树每个点的度数, 求所有满足条件的树的个数

  • 每个点到$1$的最短路唯一
  • 假设$l_i$为点$i$到$1$的最短距离, 那么$l_i\ge l_{i-1}$
  • 每个点度数范围$2\le d_i \le 3$

$dp_{i,a1,a2,b1,b2}$表示的是前$i$个点, 上一层$a_1$个度数为$1$的,$a_2$个度数为$2$的

当前层$b_1$个度数为$1$的, $b_2$个度数为$2$的方案.

暴力$O(n^5)$转移即可

好像有一个$O(n^3)$的做法 链接

#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <cstring>
#include <bitset>
#include <functional>
#include <random>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl '\n'
#define DB(a) ({REP(__i,1,n) cout<<a[__i]<<',';hr;})
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
inline int rd() {int x=0;char p=getchar();while(p<'0'||p>'9')p=getchar();while(p>='0'&&p<='9')x=x*10+p-'0',p=getchar();return x;}
//head const int N = 55;
int n, a[N], dp[2][N][N][N][N];
void add(int &a, ll b) {a=(a+b)%P;}
ll C(int x) {return (ll)x*(x-1)/2;} int main() {
scanf("%d", &n);
REP(i,1,n) scanf("%d", a+i);
int cur = 0;
dp[cur][a[1]==2][a[1]==3][a[2]==2][a[2]==3]=1;
REP(i,3,n) {
cur ^= 1;
memset(dp[cur],0,sizeof dp[0]);
PER(a1,0,i-1) PER(a2,0,i-1-a1) PER(b1,0,i-1-a1-a2) PER(b2,0,i-1-b1-a2-a1) {
ll r = dp[!cur][a1][a2][b1][b2];
if (!r) continue;
if (a[i]==2) {
//连向当前层
if (a1) add(dp[cur][a1-1][a2][b1+1][b2],a1*r);
if (a2) add(dp[cur][a1+1][a2-1][b1+1][b2],a2*r);
if (a1&&b1) add(dp[cur][a1-1][a2][b1-1][b2],a1*b1*r);
if (a1&&b2) add(dp[cur][a1-1][a2][b1+1][b2-1],a1*b2*r);
if (a2&&b1) add(dp[cur][a1+1][a2-1][b1-1][b2],a2*b1*r);
if (a2&&b2) add(dp[cur][a1+1][a2-1][b1+1][b2-1],a2*b2*r);
//连向下一层
if (!a1&&!a2) {
if (b1) add(dp[cur][b1-1][b2][1][0],b1*r);
if (b2) add(dp[cur][b1+1][b2-1][1][0],b2*r);
}
}
else {
//连向当前层
if (a1) add(dp[cur][a1-1][a2][b1][b2+1],a1*r);
if (a2) add(dp[cur][a1+1][a2-1][b1][b2+1],a2*r);
if (a1&&b1) add(dp[cur][a1-1][a2][b1][b2],a1*b1*r);
if (a1&&b2) add(dp[cur][a1-1][a2][b1+2][b2-1],a1*b2*r);
if (a2&&b1) add(dp[cur][a1+1][a2-1][b1][b2],a2*b1*r);
if (a2&&b2) add(dp[cur][a1+1][a2-1][b1+2][b2-1],a2*b2*r);
if (a1&&b1&&b2) add(dp[cur][a1-1][a2][b1][b2-1],a1*b1*b2*r);
if (a2&&b1&&b2) add(dp[cur][a1+1][a2-1][b1][b2-1],a2*b1*b2*r);
if (b1>=2&&a1) add(dp[cur][a1-1][a2][b1-2][b2],C(b1)*a1*r);
if (b1>=2&&a2) add(dp[cur][a1+1][a2-1][b1-2][b2],C(b1)*a2*r);
if (b2>=2&&a1) add(dp[cur][a1-1][a2][b1+2][b2-2],C(b2)*a1*r);
if (b2>=2&&a2) add(dp[cur][a1+1][a2-1][b1+2][b2-2],C(b2)*a2*r);
//连向下一层
if (!a1&&!a2) {
if (b1) add(dp[cur][b1-1][b2][0][1],b1*r);
if (b2) add(dp[cur][b1+1][b2-1][0][1],b2*r);
}
}
}
}
printf("%d\n",dp[cur][0][0][0][0]);
}

An unavoidable detour for home CodeForces - 814E (dp)的更多相关文章

  1. codeforces 814E An unavoidable detour for home

    题目链接 正解:$dp$. 感觉这道题就是中国象棋的加强版..我们要发现一些性质. 首先就是这个图肯定是一个按照$bfs$序分层的图,且每个点只往自己上面那一层连了一条边,每个点不可能向自己的上面超过 ...

  2. Two Melodies CodeForces - 813D (DP,技巧)

    https://codeforces.com/problemset/problem/813/D dp[i][j] = 一条链以i结尾, 另一条链以j结尾的最大值 关键要保证转移时两条链不能相交 #in ...

  3. Consecutive Subsequence CodeForces - 977F(dp)

    Consecutive Subsequence CodeForces - 977F 题目大意:输出一序列中的最大的连续数列的长度和与其对应的下标(连续是指 7 8 9这样的数列) 解题思路: 状态:把 ...

  4. codeforces的dp专题

    1.(467C)http://codeforces.com/problemset/problem/467/C 题意:有一个长为n的序列,选取k个长度为m的子序列(子序列中不能有位置重复),求所取的k个 ...

  5. Codeforces 721C [dp][拓扑排序]

    /* 题意:给你一个有向无环图.给一个限定t. 问从1点到n点,在不超过t的情况下,最多可以拜访几个点. 保证至少有一条路时限不超过t. 思路: 1.由无后向性我们可以知道(取决于该图是一个DAG), ...

  6. CodeForces 607C (DP) Hard problem

    题目:这里 题意:给定n个字符串,每个字符串可以进行一项操作,就是将这个字符串交换,就是该字符串的第一个和最后一个交换,第二个和倒数第二个交换,以此类推,当然可以选择对于 该字符串进行或不进行这项操作 ...

  7. Codeforces 611d [DP][字符串]

    /* 题意:给一个长度不超过5000的字符串,每个字符都是0到9的数字. 要求将整个字符串划分成严格递增的几个数字,并且不允许前导零. 思路: 1.很开心得发现,当我在前i个区间以后再加一个区间的时候 ...

  8. Codeforces 404D [DP]

    /* 我是一个习惯后悔,但是没办法忍受内疚感的二货== 这题是个无脑dp,但是比赛大概20min没出...其实最后5min我好好想想简单化边界条件,可以出的. 题意: 给你一个长度为1e6的由?*01 ...

  9. Codeforces 119C DP

    题意: 有n天,m门课和常数k; 每天上一门课,每门课程有两个属性,最少作业量a,最多作业量b,和难度c. 1<=a<=b<=1e16 c<=100 1<=n<=m ...

随机推荐

  1. centos7使用MariaDB(转)

    转载文章:https://blog.csdn.net/zwkkkk1/article/details/78444581?locationNum=10&fps=1 最近使用centos7,php ...

  2. unity疯狂牧场完整项目源码 - Frenzy Farming time management game kit V1.0

    You will love this game kit! Have you ever wondered what it would be like to run your own farm? Look ...

  3. JAVA基础之访问控制权限

    包:库单元 1.当编写一个Java源代码文件时,此文件通常被称为编译单元(有时也被称为转译单元). 2.每个编译单元都必须有一个后缀名.java,而在编译单元内则可以有一个public类,该类名称必须 ...

  4. Android页面切换

    参考地址: http://www.crifan.com/android_how_to_create_new_ui_and_switch_to_another_new_ui/ 想要实现,在Android ...

  5. nginx高级玩法之根据来源ip分流

    author :headsen chen date :   2019-08-15  16:37:05 notice :个人原创 需求:根据不同的请求的来源ip实现分流到不同的后端上去 方法一:1,在s ...

  6. Typescript中的可索引接口 类类型接口

    /* 5.typeScript中的接口 可索引接口 类类型接口 */ /* 接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用 ...

  7. 【转】把sqlite3数据导入到MySQL中

    之前我们默认使用的是SQLite数据库,我们开发完成之后,里面有许多数据.如果我们想转换成Mysql数据库,那我们先得把旧数据从SQLite导出,然后再导入到新的Mysql数据库里去. 1.SQLit ...

  8. ISO/IEC 9899:2011 条款6.7.2——类型说明符

    6.7.2 类型说明符 语法 1.type-specifier: void char short int long float double signed unsigned _Bool _Comple ...

  9. 获取Django model中字段名,字段的verbose_name,字段类型

    如下app:ywreport下存在model:Game: class Game(models.Model): name = models.CharField(u'游戏名称',max_length=30 ...

  10. PngOptimizer PNG压缩工具

    好用,非常好用,速度快. 把图片拖入即可,同文件夹备份替换压缩. 点击下载