HDU5579 Tower Defence (BestCoder Round #85 D) 计数dp

分析(官方题解):

一点感想:(这个题是看题解并不是特别会转移,当然写完之后看起来题解说得很清晰,主要是人太弱

这个题是参考faebdc神的代码写的,说句题外话,很荣幸高中和faebdc巨一个省,虽然本弱渣高中都没搞过oi)

最短路不等于k,所以根本不存在最短路>=k的,因为存在的话,由最短路知识可知,k+1一定是由k更新过来的,矛盾

所以最短路不等于k,即最短路小于k

然后就是不管是多校还是bc,都能碰到有关图的计数类的dp问题,比如2016多校1的刚性图,计算连通二分图的数量

这个题是计算无向图,满足最短路小于k的数量

这类题对于我来说比较难,看了题解以后可能还好一点,关键是定义状态

这个题定义的状态是f[i][j][k]很巧妙,在统计的时候可以保证不重不漏,在更新的时候,正好可以像求解最短路一样按距离一层一层更新

只能说还是太年轻,不能定义出这么好的状态,既方便统计,又方便转移,总得来说还是要努力提高姿势

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
typedef  long long LL;
const int N = 65;
const LL mod = 1e9+7;
int T,n,m;
inline LL up(LL x,LL y){
  x+=y;if(x>=mod)x-=mod;
  return x;
}
LL f[N][N][N],pw2[N*N/2],pw2_1[N],c[N][N];
void init(){
  for(int i=0;i<=60;++i){
    c[i][0]=c[i][i]=1;
    for(int j=1;j<i;++j){
      c[i][j]=up(c[i-1][j-1],c[i-1][j]);
    }
  }
  pw2_1[0]=pw2[0]=1;
  for(int i=1;i<=1800;++i)
    pw2[i]=pw2[i-1]*2%mod;
  for(int i=1;i<=60;++i)
    pw2_1[i]=pw2_1[i-1]*2%mod;
  for(int i=0;i<=60;++i)
    pw2_1[i]=up(pw2_1[i],mod-1);
  f[1][0][1]=1;
  for(int i=1;i<=60;++i)
   for(int j=0;j<i;++j)
    for(int k=1;k<=i;++k){
     if(!f[i][j][k])continue;
     LL tmp=f[i][j][k];
     for(int s=1;s+i<=60;++s){
       tmp=tmp*pw2_1[k]%mod;LL val=tmp;
       val=val*pw2[s*(s-1)/2]%mod;
       val=val*c[s+i-1][s]%mod;
       f[s+i][j+1][s]=up(f[s+i][j+1][s],val);
      }
    }
}
void work(){
   scanf("%d%d",&n,&m);LL ret=0;
   for(int i=1;i<=n;++i)
    for(int j=0;j<m;++j)
     for(int k=1;k<=i;++k){
      if(!f[i][j][k])continue;
       LL tmp=f[i][j][k];
       tmp=tmp*c[n-1][n-i]%mod;
       tmp=tmp*pw2[(n-i)*(n-i-1)/2]%mod;
       ret=up(ret,tmp);
     }
  printf("%I64d\n",ret);
}
int main(){
  init();
  scanf("%d",&T);
  for(int i=0;i<T;++i)work();
  return 0;
}

时间: 2024-08-04 06:55:37

HDU5579 Tower Defence (BestCoder Round #85 D) 计数dp的相关文章

HDU 5778 abs(暴力枚举)——BestCoder Round #85 1003

传送门 abs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1474    Accepted Submission(s): 511 Problem Description Given a number x, ask positive integer y≥2, that satisfy the following condition

Bestcoder Round #85

A:问一个长度为n小于等于100000的序列是否存在能整除m的连续子段. 前缀和之后,$ S[l,r] = S(r) - S(l-1) $ 取余m后只要查询在S里是否存在出现两次的数值即可. 注意事项:由于是多组数据的题目,一定要把上一组的数字读完,而不是得出了答案直接break!!!!!! 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 #define N 100010 6 7 us

BestCoder Round #85 sum

大晚上的更一道下午的水题吧.(虽然WA了好多次= =,但真实情况是我比较水) 描述 Given a sequence, you're asked whether there exists a consecutive subsequence whose sum is divisible by m. output YES, otherwise output NO. 输入 The first line of the input has an integer T (1≤T≤10), which repr

BestCoder Round #85(ZOJ1569尚未验证)

A题 子序列和啊,就要想到前缀和的差.这个转换一定要!记着!那么i到j的一段子序列和Sij%m ==  0就等价于(Sj-Si-1)%m == 0 了,那么什么意思呢?就是如果有两段前缀和%m的模是一样的,那么是不是就存在着一段子序列满足条件了,然后注意一下边边角角应该就没问题了.因为ZOJ坏掉了,所以我尚未验证以下答案的ans是否就是满足条件的序列总数!移步ZOJ1569自行验证. 1 #include <cstdio> 2 #include <set> 3 #include &

HDU 5776 sum (BestCoder Round #85 A) 简单前缀判断+水题

分析:就是判断简单的前缀有没有相同,注意下自身是m的倍数,以及vis[0]=true; #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <map> #include <queue> #include <vect

HDU5777 domino (BestCoder Round #85 B) 思路题+排序

分析:最终的结果肯定会分成若干个区间独立,这些若干个区间肯定是独立的(而且肯定是一边倒,左右都一样) 这样想的话,就是如何把这n-1个值分成 k份,使得和最小,那么就是简单的排序,去掉前k大的(注意longlong) #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <iostream> #include <algorithm&

HDU 5578 abs (BestCoder Round #85 C)素数筛+暴力

分析:y是一个无平方因子数的平方,所以可以从sqrt(x)向上向下枚举找到第一个无平方因子比较大小 大家可能觉得这样找过去暴力,但实际上无平方因子的分布式非常密集的,相关题目,可以参考 CDOJ:无平方因子数 http://acm.uestc.edu.cn/#/problem/show/618 这个题和CDOJ的题虽然不一样,但是可以从CDOJ发现这种数是很多的 官方题解:官方题解说这个无平方因子的枚举量在logn级别,可见非常小 #include <cstdio> #include <

HDU5780 gcd (BestCoder Round #85 E) 欧拉函数预处理——分块优化

分析(官方题解): 一点感想: 首先上面那个等式成立,然后就是求枚举gcd算贡献就好了,枚举gcd当时赛场上写了一发O(nlogn)的反演,写完过了样例,想交发现结束了 吐槽自己手速慢,但是发了题解后发现,这题连O(n)欧拉函数前缀和的都卡了,幸亏没交,还是太年轻 对于官方题解说sqrt(n)优化(其实就是n/(小于n一段数)结果是一样的,也不算什么分块),还是很简单的,做反演题的时候看到过很多,只是忘记了 如果不会请看这篇解题报告http://wenku.baidu.com/view/fbe2

HDU5807 Keep In Touch (BestCoder Round #86 D ) 分布式dp

#include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> using namespace std; typedef long long LL; const int N = 50+2; const int mod = 998244353; int T,n,m,lim,q,tot,w[N],dp[N][N][N][3],he