hdu 5779 Tower Defence
题意:考虑由$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的更多相关文章
- 动态规划(树形DP):HDU 5886 Tower Defence
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA2MAAAERCAIAAAB5Jui9AAAgAElEQVR4nOy9a6wsS3YmFL/cEkh4LP
- HDU 5886 Tower Defence
树的直径. 比赛的时候想着先树$dp$处理子树上的最长链和次长链,然后再从上到下进行一次$dfs$统计答案,和$CCPC$网络赛那个树$dp$一样,肯定是可以写的,但会很烦.......后来写崩了. ...
- HDU 5886 Tower Defence(2016青岛网络赛 I题,树的直径 + DP)
题目链接 2016 Qingdao Online Problem I 题意 在一棵给定的树上删掉一条边,求剩下两棵树的树的直径中较长那的那个长度的期望,答案乘上$n-1$后输出. 先把原来那棵树的 ...
- Hdu 2971 Tower
Description Alan loves to construct the towers of building bricks. His towers consist of many cuboid ...
- hdu 4779 Tower Defense (思维+组合数学)
Tower Defense Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others) ...
- HDU5886 Tower Defence 【两遍树形dp】【最长链预处理】
题意:N个点的一棵带权树.切掉某条边的价值为切后两树直径中的最大值.求各个边切掉后的价值和(共N-1项). 解法一: 强行两遍dp,思路繁琐,维护东西较多: dis表示以i为根的子树的直径,dis2表 ...
- HDU5779 Tower Defence (BestCoder Round #85 D) 计数dp
分析(官方题解): 一点感想:(这个题是看题解并不是特别会转移,当然写完之后看起来题解说得很清晰,主要是人太弱 这个题是参考faebdc神的代码写的,说句题外话,很荣幸高中和faebdc巨一个省,虽然 ...
- hdu 4779 Tower Defense 2013杭州现场赛
/** 题意: 有两种塔,重塔,轻塔.每种塔,能攻击他所在的一行和他所在的一列, 轻塔不 能被攻击,而重塔可以被至多一个塔攻击,也就是说重塔只能被重塔攻击.在一个n*m 的矩阵中,最少放一个塔,可放多 ...
- HDU5779 Tower Defence
dp[i][j][k] 已选i个人 选到第j层 第j层有k个人 讨论相邻层 上一层选了l人 那么共有 两层之间的方案数 以及这一层自己的方案数 #include<bits/stdc++.h&g ...
随机推荐
- JQ 队列
<div class="divtt"> <div class="divtest"></div> </div> & ...
- 使用logrotate来进行轮换mysql的慢日志
#!/bin/bash SLOWCFG=/etc/my.cnf DATADIR=`awk /^datadir/ $SLOWCFG|awk -F"=" '{print $2}'` S ...
- php获取真实IP地址
function user_realip() { if (getenv('HTTP_CLIENT_IP')) { $ip = getenv('HTTP_CLIENT_IP'); } elseif (g ...
- 【转】DNS记录类型介绍(A记录、MX记录、NS记录等)
DNS A记录 NS记录 MX记录 CNAME记录 TXT记录 TTL值 PTR值 建站名词解释:DNS A记录 NS记录 MX记录 CNAME记录 TXT记录 TTL值 PTR值 泛域名 泛解析 域 ...
- RESTful框架调研
背景 当前的开放服务平台发展趋势,是服务使用者变得多种多样,其中既有各种前端设备(台式机.手机等),又有各种后端服务器,因此必须有一个统一的机制,方便各种服务使用者和开放服务平台进行通信.为了更好的实 ...
- thinkphp3.2 cli模式的正确使用方法
最近要使用thinkphp3.2版本的cli模式,手动执的话没有问题,比如php /www/index.php home/article/get 这样没有问题,但是一般用cli模式都是定时任务比较多, ...
- mysqli_multi_query($link, $sql_w);
$sql_w = 'INSERT INTO w1 (wint) VALUES (55);'; $sql_w .= 'INSERT INTO w1 (wint) VALUES (505);'; var_ ...
- java 中设置session失效时间
程序中session都有一个默认的过期时间,其中tomcat中的默认时间为30分钟,根据需要我们可以去手动设置session的过期时间,以下是设置session的过期时间的三个方法:1.在tomcat ...
- 【Swing】理解Swing中的事件与线程
talk is cheap , show me the code. Swing中的事件 事件驱动 所有的GUI程序都是事件驱动的.Swing当然也是. GUI程序不同于Command Line程序,一 ...
- iis 部署 webapi2.0 访问报错解决
本机安装的VS2013 开发环境,在IIS部署WebApi2.0时,应用程序池并没有.NET4.5的选项. 网上搜索一番得知: 1..NET 4.5本质上还是4.0,属于递增式的更新,所以对IIS 来 ...