题意:考虑由$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)$的(快速幂看成常数时间)。

代码如下:

  1. #include <algorithm>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <string>
  5. #include <queue>
  6. #include <map>
  7. #include <set>
  8. #include <stack>
  9. #include <ctime>
  10. #include <cmath>
  11. #include <iostream>
  12. #include <assert.h>
  13. #define PI acos(-1.)
  14. #pragma comment(linker, "/STACK:102400000,102400000")
  15. #define max(a, b) ((a) > (b) ? (a) : (b))
  16. #define min(a, b) ((a) < (b) ? (a) : (b))
  17. #define mp std :: make_pair
  18. #define st first
  19. #define nd second
  20. #define keyn (root->ch[1]->ch[0])
  21. #define lson (u << 1)
  22. #define rson (u << 1 | 1)
  23. #define pii std :: pair<int, int>
  24. #define pll pair<ll, ll>
  25. #define pb push_back
  26. #define type(x) __typeof(x.begin())
  27. #define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++)
  28. #define FOR(i, s, t) for(int i = (s); i <= (t); i++)
  29. #define ROF(i, t, s) for(int i = (t); i >= (s); i--)
  30. #define dbg(x) std::cout << x << std::endl
  31. #define dbg2(x, y) std::cout << x << " " << y << std::endl
  32. #define clr(x, i) memset(x, (i), sizeof(x))
  33. #define maximize(x, y) x = max((x), (y))
  34. #define minimize(x, y) x = min((x), (y))
  35. using namespace std;
  36. typedef long long ll;
  37. const int int_inf = 0x3f3f3f3f;
  38. const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
  39. const int INT_INF = (int)((1ll << ) - );
  40. const double double_inf = 1e30;
  41. const double eps = 1e-;
  42. typedef unsigned long long ul;
  43. typedef unsigned int ui;
  44. inline int readint(){
  45. int x;
  46. scanf("%d", &x);
  47. return x;
  48. }
  49. inline int readstr(char *s){
  50. scanf("%s", s);
  51. return strlen(s);
  52. }
  53. //Here goes 2d geometry templates
  54. struct Point{
  55. double x, y;
  56. Point(double x = , double y = ) : x(x), y(y) {}
  57. };
  58. typedef Point Vector;
  59. Vector operator + (Vector A, Vector B){
  60. return Vector(A.x + B.x, A.y + B.y);
  61. }
  62. Vector operator - (Point A, Point B){
  63. return Vector(A.x - B.x, A.y - B.y);
  64. }
  65. Vector operator * (Vector A, double p){
  66. return Vector(A.x * p, A.y * p);
  67. }
  68. Vector operator / (Vector A, double p){
  69. return Vector(A.x / p, A.y / p);
  70. }
  71. bool operator < (const Point& a, const Point& b){
  72. return a.x < b.x || (a.x == b.x && a.y < b.y);
  73. }
  74. int dcmp(double x){
  75. if(abs(x) < eps) return ;
  76. return x < ? - : ;
  77. }
  78. bool operator == (const Point& a, const Point& b){
  79. return dcmp(a.x - b.x) == && dcmp(a.y - b.y) == ;
  80. }
  81. double Dot(Vector A, Vector B){
  82. return A.x * B.x + A.y * B.y;
  83. }
  84. double Len(Vector A){
  85. return sqrt(Dot(A, A));
  86. }
  87. double Angle(Vector A, Vector B){
  88. return acos(Dot(A, B) / Len(A) / Len(B));
  89. }
  90. double Cross(Vector A, Vector B){
  91. return A.x * B.y - A.y * B.x;
  92. }
  93. double Area2(Point A, Point B, Point C){
  94. return Cross(B - A, C - A);
  95. }
  96. Vector Rotate(Vector A, double rad){
  97. //rotate counterclockwise
  98. return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
  99. }
  100. Vector Normal(Vector A){
  101. double L = Len(A);
  102. return Vector(-A.y / L, A.x / L);
  103. }
  104. void Normallize(Vector &A){
  105. double L = Len(A);
  106. A.x /= L, A.y /= L;
  107. }
  108. Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){
  109. Vector u = P - Q;
  110. double t = Cross(w, u) / Cross(v, w);
  111. return P + v * t;
  112. }
  113. double DistanceToLine(Point P, Point A, Point B){
  114. Vector v1 = B - A, v2 = P - A;
  115. return abs(Cross(v1, v2)) / Len(v1);
  116. }
  117. double DistanceToSegment(Point P, Point A, Point B){
  118. if(A == B) return Len(P - A);
  119. Vector v1 = B - A, v2 = P - A, v3 = P - B;
  120. if(dcmp(Dot(v1, v2)) < ) return Len(v2);
  121. else if(dcmp(Dot(v1, v3)) > ) return Len(v3);
  122. else return abs(Cross(v1, v2)) / Len(v1);
  123. }
  124. Point GetLineProjection(Point P, Point A, Point B){
  125. Vector v = B - A;
  126. return A + v * (Dot(v, P - A) / Dot(v, v));
  127. }
  128. bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2){
  129. //Line1:(a1, a2) Line2:(b1,b2)
  130. double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
  131. c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
  132. return dcmp(c1) * dcmp(c2) < && dcmp(c3) * dcmp(c4) < ;
  133. }
  134. bool OnSegment(Point p, Point a1, Point a2){
  135. return dcmp(Cross(a1 - p, a2 - p)) == && dcmp(Dot(a1 - p, a2 -p)) < ;
  136. }
  137. Vector GetBisector(Vector v, Vector w){
  138. Normallize(v), Normallize(w);
  139. return Vector((v.x + w.x) / , (v.y + w.y) / );
  140. }
  141.  
  142. bool OnLine(Point p, Point a1, Point a2){
  143. Vector v1 = p - a1, v2 = a2 - a1;
  144. double tem = Cross(v1, v2);
  145. return dcmp(tem) == ;
  146. }
  147. struct Line{
  148. Point p;
  149. Vector v;
  150. Point point(double t){
  151. return Point(p.x + t * v.x, p.y + t * v.y);
  152. }
  153. Line(Point p, Vector v) : p(p), v(v) {}
  154. };
  155. struct Circle{
  156. Point c;
  157. double r;
  158. Circle(Point c, double r) : c(c), r(r) {}
  159. Circle(int x, int y, int _r){
  160. c = Point(x, y);
  161. r = _r;
  162. }
  163. Point point(double a){
  164. return Point(c.x + cos(a) * r, c.y + sin(a) * r);
  165. }
  166. };
  167. int GetLineCircleIntersection(Line L, Circle C, double &t1, double& t2, std :: vector<Point>& sol){
  168. double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
  169. double e = a * a + c * c, f = * (a * b + c * d), g = b * b + d * d - C.r * C.r;
  170. double delta = f * f - * e * g;
  171. if(dcmp(delta) < ) return ;
  172. if(dcmp(delta) == ){
  173. t1 = t2 = -f / ( * e); sol.pb(L.point(t1));
  174. return ;
  175. }
  176. t1 = (-f - sqrt(delta)) / ( * e); sol.pb(L.point(t1));
  177. t2 = (-f + sqrt(delta)) / ( * e); sol.pb(L.point(t2));
  178. return ;
  179. }
  180. double angle(Vector v){
  181. return atan2(v.y, v.x);
  182. //(-pi, pi]
  183. }
  184. int GetCircleCircleIntersection(Circle C1, Circle C2, std :: vector<Point>& sol){
  185. double d = Len(C1.c - C2.c);
  186. if(dcmp(d) == ){
  187. if(dcmp(C1.r - C2.r) == ) return -; //two circle duplicates
  188. return ; //two circles share identical center
  189. }
  190. if(dcmp(C1.r + C2.r - d) < ) return ; //too close
  191. if(dcmp(abs(C1.r - C2.r) - d) > ) return ; //too far away
  192. double a = angle(C2.c - C1.c); // angle of vector(C1, C2)
  193. double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / ( * C1.r * d));
  194. Point p1 = C1.point(a - da), p2 = C1.point(a + da);
  195. sol.pb(p1);
  196. if(p1 == p2) return ;
  197. sol.pb(p2);
  198. return ;
  199. }
  200. int GetPointCircleTangents(Point p, Circle C, Vector* v){
  201. Vector u = C.c - p;
  202. double dist = Len(u);
  203. if(dist < C.r) return ;//p is inside the circle, no tangents
  204. else if(dcmp(dist - C.r) == ){
  205. // p is on the circles, one tangent only
  206. v[] = Rotate(u, PI / );
  207. return ;
  208. }else{
  209. double ang = asin(C.r / dist);
  210. v[] = Rotate(u, -ang);
  211. v[] = Rotate(u, +ang);
  212. return ;
  213. }
  214. }
  215. int GetCircleCircleTangents(Circle A, Circle B, Point* a, Point* b){
  216. //a[i] store point of tangency on Circle A of tangent i
  217. //b[i] store point of tangency on Circle B of tangent i
  218. //six conditions is in consideration
  219. int cnt = ;
  220. if(A.r < B.r) { std :: swap(A, B); std :: swap(a, b); }
  221. 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);
  222. int rdiff = A.r - B.r;
  223. int rsum = A.r + B.r;
  224. if(d2 < rdiff * rdiff) return ; // one circle is inside the other
  225. double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);
  226. if(d2 == && A.r == B.r) return -; // two circle duplicates
  227. if(d2 == rdiff * rdiff){ // internal tangency
  228. a[cnt] = A.point(base); b[cnt] = B.point(base); cnt++;
  229. return ;
  230. }
  231. double ang = acos((A.r - B.r) / sqrt(d2));
  232. a[cnt] = A.point(base + ang); b[cnt++] = B.point(base + ang);
  233. a[cnt] = A.point(base - ang); b[cnt++] = B.point(base - ang);
  234. if(d2 == rsum * rsum){
  235. //one internal tangent
  236. a[cnt] = A.point(base);
  237. b[cnt++] = B.point(base + PI);
  238. }else if(d2 > rsum * rsum){
  239. //two internal tangents
  240. double ang = acos((A.r + B.r) / sqrt(d2));
  241. a[cnt] = A.point(base + ang); b[cnt++] = B.point(base + ang + PI);
  242. a[cnt] = A.point(base - ang); b[cnt++] = B.point(base - ang + PI);
  243. }
  244. return cnt;
  245. }
  246. Point ReadPoint(){
  247. double x, y;
  248. scanf("%lf%lf", &x, &y);
  249. return Point(x, y);
  250. }
  251. Circle ReadCircle(){
  252. double x, y, r;
  253. scanf("%lf%lf%lf", &x, &y, &r);
  254. return Circle(x, y, r);
  255. }
  256. //Here goes 3d geometry templates
  257. struct Point3{
  258. double x, y, z;
  259. Point3(double x = , double y = , double z = ) : x(x), y(y), z(z) {}
  260. };
  261. typedef Point3 Vector3;
  262. Vector3 operator + (Vector3 A, Vector3 B){
  263. return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);
  264. }
  265. Vector3 operator - (Vector3 A, Vector3 B){
  266. return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);
  267. }
  268. Vector3 operator * (Vector3 A, double p){
  269. return Vector3(A.x * p, A.y * p, A.z * p);
  270. }
  271. Vector3 operator / (Vector3 A, double p){
  272. return Vector3(A.x / p, A.y / p, A.z / p);
  273. }
  274. double Dot3(Vector3 A, Vector3 B){
  275. return A.x * B.x + A.y * B.y + A.z * B.z;
  276. }
  277. double Len3(Vector3 A){
  278. return sqrt(Dot3(A, A));
  279. }
  280. double Angle3(Vector3 A, Vector3 B){
  281. return acos(Dot3(A, B) / Len3(A) / Len3(B));
  282. }
  283. double DistanceToPlane(const Point3& p, const Point3 &p0, const Vector3& n){
  284. return abs(Dot3(p - p0, n));
  285. }
  286. Point3 GetPlaneProjection(const Point3 &p, const Point3 &p0, const Vector3 &n){
  287. return p - n * Dot3(p - p0, n);
  288. }
  289. Point3 GetLinePlaneIntersection(Point3 p1, Point3 p2, Point3 p0, Vector3 n){
  290. Vector3 v = p2 - p1;
  291. double t = (Dot3(n, p0 - p1) / Dot3(n, p2 - p1));
  292. return p1 + v * t;//if t in range [0, 1], intersection on segment
  293. }
  294. Vector3 Cross(Vector3 A, Vector3 B){
  295. 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);
  296. }
  297. double Area3(Point3 A, Point3 B, Point3 C){
  298. return Len3(Cross(B - A, C - A));
  299. }
  300. class cmpt{
  301. public:
  302. bool operator () (const int &x, const int &y) const{
  303. return x > y;
  304. }
  305. };
  306.  
  307. int Rand(int x, int o){
  308. //if o set, return [1, x], else return [0, x - 1]
  309. if(!x) return ;
  310. int tem = (int)((double)rand() / RAND_MAX * x) % x;
  311. return o ? tem + : tem;
  312. }
  313. void data_gen(){
  314. srand(time());
  315. freopen("in.txt", "w", stdout);
  316. int kases = ;
  317. printf("%d\n", kases);
  318. while(kases--){
  319. int sz = 2e4;
  320. int m = 1e5;
  321. printf("%d %d\n", sz, m);
  322. FOR(i, , sz) printf("%d ", Rand(, ));
  323. printf("\n");
  324. FOR(i, , sz) printf("%d ", Rand(1e9, ));
  325. printf("\n");
  326. FOR(i, , m){
  327. int l = Rand(sz, );
  328. int r = Rand(sz, );
  329. int c = Rand(1e9, );
  330. printf("%d %d %d %d\n", l, r, c, Rand(, ));
  331. }
  332. }
  333. }
  334.  
  335. struct cmpx{
  336. bool operator () (int x, int y) { return x > y; }
  337. };
  338.  
  339. const int maxn = ;
  340. const int mod = 1e9 + ;
  341. ll power(ll a, ll p, ll mod){
  342. ll ans = ;
  343. a %= mod;
  344. while(p){
  345. if(p & ) ans = ans * a % mod;
  346. p >>= ;
  347. a = a * a % mod;
  348. }
  349. return ans;
  350. }
  351. ll dp[maxn][maxn][maxn];
  352. ll C[maxn][maxn];
  353. ll pow2[maxn * maxn];
  354. ll pow_pow[maxn][maxn];
  355. void init(){
  356. clr(dp, ), clr(C, );
  357. int lim = ;
  358. clr(C, );
  359. C[][] = ;
  360. FOR(i, , lim) C[i][] = C[i][i] = ;
  361. FOR(i, , lim) FOR(j, , i - ) C[i][j] = (C[i - ][j] + C[i - ][j - ]) % mod;
  362. pow2[] = ;
  363. FOR(i, , lim * lim) pow2[i] = pow2[i - ] * % mod;
  364. FOR(i, , lim) FOR(j, , lim) pow_pow[i][j] = power((1ll << i) - , j, mod);
  365. dp[][][] = ;
  366. FOR(i, , lim) FOR(k, , i) FOR(j, , i) FOR(u, , i - j){
  367. ll tem = C[i - ][j] * pow_pow[u][j] % mod * pow2[C[j][]] % mod;
  368. dp[i][j][k] = (dp[i][j][k] + dp[i - j][u][k - ] * tem % mod) % mod;
  369. }
  370. }
  371. ll cal(int n, int k){
  372. ll ans = ;
  373. FOR(u, , n) FOR(i, , k - ) FOR(j, , u){
  374. ll para = pow2[C[n - u][]] * C[n - ][n - u] % mod;
  375. ans = (ans + para * dp[u][j][i] % mod) % mod;
  376. }
  377. return ans;
  378. }
  379. int main(){
  380. //data_gen(); return 0;
  381. //C(); return 0;
  382. int debug = ;
  383. if(debug) freopen("in.txt", "r", stdin);
  384. //freopen("out.txt", "w", stdout);
  385. init();
  386. int T = readint();
  387. while(T--){
  388. int n = readint(), k = readint();
  389. printf("%lld\n", cal(n, k));
  390. }
  391. return ;
  392. }

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. JQ 队列

    <div class="divtt"> <div class="divtest"></div> </div> & ...

  2. 使用logrotate来进行轮换mysql的慢日志

    #!/bin/bash SLOWCFG=/etc/my.cnf DATADIR=`awk /^datadir/ $SLOWCFG|awk -F"=" '{print $2}'` S ...

  3. php获取真实IP地址

    function user_realip() { if (getenv('HTTP_CLIENT_IP')) { $ip = getenv('HTTP_CLIENT_IP'); } elseif (g ...

  4. 【转】DNS记录类型介绍(A记录、MX记录、NS记录等)

    DNS A记录 NS记录 MX记录 CNAME记录 TXT记录 TTL值 PTR值 建站名词解释:DNS A记录 NS记录 MX记录 CNAME记录 TXT记录 TTL值 PTR值 泛域名 泛解析 域 ...

  5. RESTful框架调研

    背景 当前的开放服务平台发展趋势,是服务使用者变得多种多样,其中既有各种前端设备(台式机.手机等),又有各种后端服务器,因此必须有一个统一的机制,方便各种服务使用者和开放服务平台进行通信.为了更好的实 ...

  6. thinkphp3.2 cli模式的正确使用方法

    最近要使用thinkphp3.2版本的cli模式,手动执的话没有问题,比如php /www/index.php home/article/get 这样没有问题,但是一般用cli模式都是定时任务比较多, ...

  7. mysqli_multi_query($link, $sql_w);

    $sql_w = 'INSERT INTO w1 (wint) VALUES (55);'; $sql_w .= 'INSERT INTO w1 (wint) VALUES (505);'; var_ ...

  8. java 中设置session失效时间

    程序中session都有一个默认的过期时间,其中tomcat中的默认时间为30分钟,根据需要我们可以去手动设置session的过期时间,以下是设置session的过期时间的三个方法:1.在tomcat ...

  9. 【Swing】理解Swing中的事件与线程

    talk is cheap , show me the code. Swing中的事件 事件驱动 所有的GUI程序都是事件驱动的.Swing当然也是. GUI程序不同于Command Line程序,一 ...

  10. iis 部署 webapi2.0 访问报错解决

    本机安装的VS2013 开发环境,在IIS部署WebApi2.0时,应用程序池并没有.NET4.5的选项. 网上搜索一番得知: 1..NET 4.5本质上还是4.0,属于递增式的更新,所以对IIS 来 ...