题意:考虑由$n$个结点构成的无向图,每条边的长度均为$1$,问有多少种构图方法使得结点$1$与任意其它节点之间的最短距离均不等于$k$(无法到达时距离等于无穷大),输出答案对$1e9+7$取模。$1 \leq n, k \leq 60$。

分析:只需要考虑那些和结点$1$在同一个连通块的结点,考虑对包含结点$1$的连通图的等价类划分:首先是结点数目,其次是所有结点到达结点$1$的最短距离的最大值,再次是最短距离等于该最大值的结点数目,因此用$dp(i, j, k)$表示与$1$在同一个连通分量的图中,结点数目为$i$,最短距离最大值为$k$,距离$1$最远的结点数目为$j$的数目。考虑这样的构图方式:图$(i, j, k)$中到结点$1$距离为$k$的结点必然是其子图中距离$1$距离为$k-1$的结点的直接后继,因此考虑删除$j$个这样的点,得到图$(i-j, u, k - 1)$,其中$u$表示子图中到结点$1$距离为$k-1$的结点数目。由于$j$个点内部的连接方式不影响(不会减少)其距离,因此全部$2^{\frac{j(j-1)}{2}}$种连接方法均是合法的,而每个结点至少是$u$个结点之一的后继,因此连法有$(2^{u}-1)^j$种,又因为所有点都不相同,组合系数为$\textrm {C}_{i-1}^{j}$,因此可以这样计算图类$(i,j,k)$的总数:$dp(i, j, k) = \sum_{u=1}^{i-j}{dp(i-j,u,k-1)\cdot\textrm {C}_{i-1}^{j}\cdot {(2^{u}-1)}^j \cdot 2^{\frac{j(j-1)}{2}}}$。再考虑边界条件,显然$dp(1,1,0)=1$,其余在初始时清零即可。这样预处理的时间复杂度是$O(n^3 \cdot n) = O(n^4)$的(快速幂看成常数时间)。

代码如下:

 #include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <ctime>
#include <cmath>
#include <iostream>
#include <assert.h>
#define PI acos(-1.)
#pragma comment(linker, "/STACK:102400000,102400000")
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define mp std :: make_pair
#define st first
#define nd second
#define keyn (root->ch[1]->ch[0])
#define lson (u << 1)
#define rson (u << 1 | 1)
#define pii std :: pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define type(x) __typeof(x.begin())
#define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++)
#define FOR(i, s, t) for(int i = (s); i <= (t); i++)
#define ROF(i, t, s) for(int i = (t); i >= (s); i--)
#define dbg(x) std::cout << x << std::endl
#define dbg2(x, y) std::cout << x << " " << y << std::endl
#define clr(x, i) memset(x, (i), sizeof(x))
#define maximize(x, y) x = max((x), (y))
#define minimize(x, y) x = min((x), (y))
using namespace std;
typedef long long ll;
const int int_inf = 0x3f3f3f3f;
const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
const int INT_INF = (int)((1ll << ) - );
const double double_inf = 1e30;
const double eps = 1e-;
typedef unsigned long long ul;
typedef unsigned int ui;
inline int readint(){
int x;
scanf("%d", &x);
return x;
}
inline int readstr(char *s){
scanf("%s", s);
return strlen(s);
}
//Here goes 2d geometry templates
struct Point{
double x, y;
Point(double x = , double y = ) : x(x), y(y) {}
};
typedef Point Vector;
Vector operator + (Vector A, Vector B){
return Vector(A.x + B.x, A.y + B.y);
}
Vector operator - (Point A, Point B){
return Vector(A.x - B.x, A.y - B.y);
}
Vector operator * (Vector A, double p){
return Vector(A.x * p, A.y * p);
}
Vector operator / (Vector A, double p){
return Vector(A.x / p, A.y / p);
}
bool operator < (const Point& a, const Point& b){
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
int dcmp(double x){
if(abs(x) < eps) return ;
return x < ? - : ;
}
bool operator == (const Point& a, const Point& b){
return dcmp(a.x - b.x) == && dcmp(a.y - b.y) == ;
}
double Dot(Vector A, Vector B){
return A.x * B.x + A.y * B.y;
}
double Len(Vector A){
return sqrt(Dot(A, A));
}
double Angle(Vector A, Vector B){
return acos(Dot(A, B) / Len(A) / Len(B));
}
double Cross(Vector A, Vector B){
return A.x * B.y - A.y * B.x;
}
double Area2(Point A, Point B, Point C){
return Cross(B - A, C - A);
}
Vector Rotate(Vector A, double rad){
//rotate counterclockwise
return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
}
Vector Normal(Vector A){
double L = Len(A);
return Vector(-A.y / L, A.x / L);
}
void Normallize(Vector &A){
double L = Len(A);
A.x /= L, A.y /= L;
}
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){
Vector u = P - Q;
double t = Cross(w, u) / Cross(v, w);
return P + v * t;
}
double DistanceToLine(Point P, Point A, Point B){
Vector v1 = B - A, v2 = P - A;
return abs(Cross(v1, v2)) / Len(v1);
}
double DistanceToSegment(Point P, Point A, Point B){
if(A == B) return Len(P - A);
Vector v1 = B - A, v2 = P - A, v3 = P - B;
if(dcmp(Dot(v1, v2)) < ) return Len(v2);
else if(dcmp(Dot(v1, v3)) > ) return Len(v3);
else return abs(Cross(v1, v2)) / Len(v1);
}
Point GetLineProjection(Point P, Point A, Point B){
Vector v = B - A;
return A + v * (Dot(v, P - A) / Dot(v, v));
}
bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2){
//Line1:(a1, a2) Line2:(b1,b2)
double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
return dcmp(c1) * dcmp(c2) < && dcmp(c3) * dcmp(c4) < ;
}
bool OnSegment(Point p, Point a1, Point a2){
return dcmp(Cross(a1 - p, a2 - p)) == && dcmp(Dot(a1 - p, a2 -p)) < ;
}
Vector GetBisector(Vector v, Vector w){
Normallize(v), Normallize(w);
return Vector((v.x + w.x) / , (v.y + w.y) / );
} bool OnLine(Point p, Point a1, Point a2){
Vector v1 = p - a1, v2 = a2 - a1;
double tem = Cross(v1, v2);
return dcmp(tem) == ;
}
struct Line{
Point p;
Vector v;
Point point(double t){
return Point(p.x + t * v.x, p.y + t * v.y);
}
Line(Point p, Vector v) : p(p), v(v) {}
};
struct Circle{
Point c;
double r;
Circle(Point c, double r) : c(c), r(r) {}
Circle(int x, int y, int _r){
c = Point(x, y);
r = _r;
}
Point point(double a){
return Point(c.x + cos(a) * r, c.y + sin(a) * r);
}
};
int GetLineCircleIntersection(Line L, Circle C, double &t1, double& t2, std :: vector<Point>& sol){
double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
double e = a * a + c * c, f = * (a * b + c * d), g = b * b + d * d - C.r * C.r;
double delta = f * f - * e * g;
if(dcmp(delta) < ) return ;
if(dcmp(delta) == ){
t1 = t2 = -f / ( * e); sol.pb(L.point(t1));
return ;
}
t1 = (-f - sqrt(delta)) / ( * e); sol.pb(L.point(t1));
t2 = (-f + sqrt(delta)) / ( * e); sol.pb(L.point(t2));
return ;
}
double angle(Vector v){
return atan2(v.y, v.x);
//(-pi, pi]
}
int GetCircleCircleIntersection(Circle C1, Circle C2, std :: vector<Point>& sol){
double d = Len(C1.c - C2.c);
if(dcmp(d) == ){
if(dcmp(C1.r - C2.r) == ) return -; //two circle duplicates
return ; //two circles share identical center
}
if(dcmp(C1.r + C2.r - d) < ) return ; //too close
if(dcmp(abs(C1.r - C2.r) - d) > ) return ; //too far away
double a = angle(C2.c - C1.c); // angle of vector(C1, C2)
double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / ( * C1.r * d));
Point p1 = C1.point(a - da), p2 = C1.point(a + da);
sol.pb(p1);
if(p1 == p2) return ;
sol.pb(p2);
return ;
}
int GetPointCircleTangents(Point p, Circle C, Vector* v){
Vector u = C.c - p;
double dist = Len(u);
if(dist < C.r) return ;//p is inside the circle, no tangents
else if(dcmp(dist - C.r) == ){
// p is on the circles, one tangent only
v[] = Rotate(u, PI / );
return ;
}else{
double ang = asin(C.r / dist);
v[] = Rotate(u, -ang);
v[] = Rotate(u, +ang);
return ;
}
}
int GetCircleCircleTangents(Circle A, Circle B, Point* a, Point* b){
//a[i] store point of tangency on Circle A of tangent i
//b[i] store point of tangency on Circle B of tangent i
//six conditions is in consideration
int cnt = ;
if(A.r < B.r) { std :: swap(A, B); std :: swap(a, b); }
int d2 = (A.c.x - B.c.x) * (A.c.x - B.c.x) + (A.c.y - B.c.y) * (A.c.y - B.c.y);
int rdiff = A.r - B.r;
int rsum = A.r + B.r;
if(d2 < rdiff * rdiff) return ; // one circle is inside the other
double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);
if(d2 == && A.r == B.r) return -; // two circle duplicates
if(d2 == rdiff * rdiff){ // internal tangency
a[cnt] = A.point(base); b[cnt] = B.point(base); cnt++;
return ;
}
double ang = acos((A.r - B.r) / sqrt(d2));
a[cnt] = A.point(base + ang); b[cnt++] = B.point(base + ang);
a[cnt] = A.point(base - ang); b[cnt++] = B.point(base - ang);
if(d2 == rsum * rsum){
//one internal tangent
a[cnt] = A.point(base);
b[cnt++] = B.point(base + PI);
}else if(d2 > rsum * rsum){
//two internal tangents
double ang = acos((A.r + B.r) / sqrt(d2));
a[cnt] = A.point(base + ang); b[cnt++] = B.point(base + ang + PI);
a[cnt] = A.point(base - ang); b[cnt++] = B.point(base - ang + PI);
}
return cnt;
}
Point ReadPoint(){
double x, y;
scanf("%lf%lf", &x, &y);
return Point(x, y);
}
Circle ReadCircle(){
double x, y, r;
scanf("%lf%lf%lf", &x, &y, &r);
return Circle(x, y, r);
}
//Here goes 3d geometry templates
struct Point3{
double x, y, z;
Point3(double x = , double y = , double z = ) : x(x), y(y), z(z) {}
};
typedef Point3 Vector3;
Vector3 operator + (Vector3 A, Vector3 B){
return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);
}
Vector3 operator - (Vector3 A, Vector3 B){
return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);
}
Vector3 operator * (Vector3 A, double p){
return Vector3(A.x * p, A.y * p, A.z * p);
}
Vector3 operator / (Vector3 A, double p){
return Vector3(A.x / p, A.y / p, A.z / p);
}
double Dot3(Vector3 A, Vector3 B){
return A.x * B.x + A.y * B.y + A.z * B.z;
}
double Len3(Vector3 A){
return sqrt(Dot3(A, A));
}
double Angle3(Vector3 A, Vector3 B){
return acos(Dot3(A, B) / Len3(A) / Len3(B));
}
double DistanceToPlane(const Point3& p, const Point3 &p0, const Vector3& n){
return abs(Dot3(p - p0, n));
}
Point3 GetPlaneProjection(const Point3 &p, const Point3 &p0, const Vector3 &n){
return p - n * Dot3(p - p0, n);
}
Point3 GetLinePlaneIntersection(Point3 p1, Point3 p2, Point3 p0, Vector3 n){
Vector3 v = p2 - p1;
double t = (Dot3(n, p0 - p1) / Dot3(n, p2 - p1));
return p1 + v * t;//if t in range [0, 1], intersection on segment
}
Vector3 Cross(Vector3 A, Vector3 B){
return Vector3(A.y * B.z - A.z * B.y, A.z * B.x - A.x * B.z, A.x * B.y - A.y * B.x);
}
double Area3(Point3 A, Point3 B, Point3 C){
return Len3(Cross(B - A, C - A));
}
class cmpt{
public:
bool operator () (const int &x, const int &y) const{
return x > y;
}
}; int Rand(int x, int o){
//if o set, return [1, x], else return [0, x - 1]
if(!x) return ;
int tem = (int)((double)rand() / RAND_MAX * x) % x;
return o ? tem + : tem;
}
void data_gen(){
srand(time());
freopen("in.txt", "w", stdout);
int kases = ;
printf("%d\n", kases);
while(kases--){
int sz = 2e4;
int m = 1e5;
printf("%d %d\n", sz, m);
FOR(i, , sz) printf("%d ", Rand(, ));
printf("\n");
FOR(i, , sz) printf("%d ", Rand(1e9, ));
printf("\n");
FOR(i, , m){
int l = Rand(sz, );
int r = Rand(sz, );
int c = Rand(1e9, );
printf("%d %d %d %d\n", l, r, c, Rand(, ));
}
}
} struct cmpx{
bool operator () (int x, int y) { return x > y; }
}; const int maxn = ;
const int mod = 1e9 + ;
ll power(ll a, ll p, ll mod){
ll ans = ;
a %= mod;
while(p){
if(p & ) ans = ans * a % mod;
p >>= ;
a = a * a % mod;
}
return ans;
}
ll dp[maxn][maxn][maxn];
ll C[maxn][maxn];
ll pow2[maxn * maxn];
ll pow_pow[maxn][maxn];
void init(){
clr(dp, ), clr(C, );
int lim = ;
clr(C, );
C[][] = ;
FOR(i, , lim) C[i][] = C[i][i] = ;
FOR(i, , lim) FOR(j, , i - ) C[i][j] = (C[i - ][j] + C[i - ][j - ]) % mod;
pow2[] = ;
FOR(i, , lim * lim) pow2[i] = pow2[i - ] * % mod;
FOR(i, , lim) FOR(j, , lim) pow_pow[i][j] = power((1ll << i) - , j, mod);
dp[][][] = ;
FOR(i, , lim) FOR(k, , i) FOR(j, , i) FOR(u, , i - j){
ll tem = C[i - ][j] * pow_pow[u][j] % mod * pow2[C[j][]] % mod;
dp[i][j][k] = (dp[i][j][k] + dp[i - j][u][k - ] * tem % mod) % mod;
}
}
ll cal(int n, int k){
ll ans = ;
FOR(u, , n) FOR(i, , k - ) FOR(j, , u){
ll para = pow2[C[n - u][]] * C[n - ][n - u] % mod;
ans = (ans + para * dp[u][j][i] % mod) % mod;
}
return ans;
}
int main(){
//data_gen(); return 0;
//C(); return 0;
int debug = ;
if(debug) freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
init();
int T = readint();
while(T--){
int n = readint(), k = readint();
printf("%lld\n", cal(n, k));
}
return ;
}

hdu 5779 code:

hdu 5779 Tower Defence的更多相关文章

  1. 动态规划(树形DP):HDU 5886 Tower Defence

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA2MAAAERCAIAAAB5Jui9AAAgAElEQVR4nOy9a6wsS3YmFL/cEkh4LP

  2. HDU 5886 Tower Defence

    树的直径. 比赛的时候想着先树$dp$处理子树上的最长链和次长链,然后再从上到下进行一次$dfs$统计答案,和$CCPC$网络赛那个树$dp$一样,肯定是可以写的,但会很烦.......后来写崩了. ...

  3. HDU 5886 Tower Defence(2016青岛网络赛 I题,树的直径 + DP)

    题目链接  2016 Qingdao Online Problem I 题意  在一棵给定的树上删掉一条边,求剩下两棵树的树的直径中较长那的那个长度的期望,答案乘上$n-1$后输出. 先把原来那棵树的 ...

  4. Hdu 2971 Tower

    Description Alan loves to construct the towers of building bricks. His towers consist of many cuboid ...

  5. hdu 4779 Tower Defense (思维+组合数学)

    Tower Defense Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) ...

  6. HDU5886 Tower Defence 【两遍树形dp】【最长链预处理】

    题意:N个点的一棵带权树.切掉某条边的价值为切后两树直径中的最大值.求各个边切掉后的价值和(共N-1项). 解法一: 强行两遍dp,思路繁琐,维护东西较多: dis表示以i为根的子树的直径,dis2表 ...

  7. HDU5779 Tower Defence (BestCoder Round #85 D) 计数dp

    分析(官方题解): 一点感想:(这个题是看题解并不是特别会转移,当然写完之后看起来题解说得很清晰,主要是人太弱 这个题是参考faebdc神的代码写的,说句题外话,很荣幸高中和faebdc巨一个省,虽然 ...

  8. hdu 4779 Tower Defense 2013杭州现场赛

    /** 题意: 有两种塔,重塔,轻塔.每种塔,能攻击他所在的一行和他所在的一列, 轻塔不 能被攻击,而重塔可以被至多一个塔攻击,也就是说重塔只能被重塔攻击.在一个n*m 的矩阵中,最少放一个塔,可放多 ...

  9. HDU5779 Tower Defence

    dp[i][j][k] 已选i个人 选到第j层 第j层有k个人 讨论相邻层  上一层选了l人 那么共有 两层之间的方案数 以及这一层自己的方案数 #include<bits/stdc++.h&g ...

随机推荐

  1. Daily Scrum 10.28

    今天是周一,大家基本都结束了设计阶段转入代码实现的阶段,由于同志们感觉这部分的难度比较大,所以经过讨论延长了这部分的估计时间. 下面是今天的Task统计: 所有迭代的状态:

  2. oracle initialization or shutdown in progress问题解决步骤

        今天像往常一样打开电脑,启动plsql工具连接数据库,但是尽然连接不了,报了“oracle initialization or shutdown in progress”的提示信息,从操作系统 ...

  3. Android课程---进度条及菜单的学习

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  4. 【转】java开源类库pinyin4j的使用

    最近CMS系统为了增加查询的匹配率,需要增加拼音检索字段,在网上找到了pinyin4j的java开源类库,提供中文转汉语拼音(并且支持多音字), 呵呵,看了看他的demo,决定就用它了,因为我在实际使 ...

  5. sqlplus 初始化文件(每一次打开sqlplus不用重新设置 linesize 和 pagesize)

    初始化文件目录  D:\oracle\product\11.2.0\dbhome_1\sqlplus\admin\glogin.sql 用记事本打开,添加 --SET linesize 150SET ...

  6. 将公网IP自动发到Twitter上

    [Twitter] 1. 在https://apps.twitter.com/创建新的应用 2. 在https://dev.twitter.com/rest/reference/post/status ...

  7. MySQL 启动时禁用了 InnoDB 引擎的解决方法

    今天在从本地数据库复制表数据到虚拟机 CentOS 6.6 上的数据库时,得到提示: Unknown table engine 'InnoDB' 于是在服务器 MySQL 中查看了引擎: mysql& ...

  8. 从.NET和Java之争谈IT这个行业[转]

    一.有些事情难以回头 开篇我得表名自己的立场:.NET JAVA同时使用者,但更加偏爱.NET.原因很简单 1.NET语言更具开放性,从开源协议和规范可以看出; 2.语言更具优势严谨; 3.开发工具V ...

  9. ETL的数据来源,处理,保存

    1.ETL 数据来源:HDFS 处理方式:Mapreduce 数据保存:HBase 2.为什么保存在Hbase中 数据字段格式不唯一/不相同/不固定,采用hbase的动态列的功能非常适合 因为我们的分 ...

  10. Airline Hub

    参考:http://blog.csdn.net/mobius_strip/article/details/12731459 #include <stdio.h> #include < ...