(上不了p站我要死了)

啊啊,其实想清楚了还是挺简单的。

Description

小宇从历史书上了解到一个古老的文明。这个文明在各个方面高度发达,交通方面也不例外。考古学家已经知道,这个文明在全盛时期有n座城市,编号为1..n。m条道路连接在这些城市之间,每条道路将两个城市连接起来,使得两地的居民可以方便地来往。一对城市之间可能存在多条道路。

据史料记载,这个文明的交通网络满足两个奇怪的特征。首先,这个文明崇拜数字K,所以对于任何一条道路,设它连接的两个城市分别为u和v,则必定满足1 <=|u - v| <= K。此外,任何一个城市都与恰好偶数条道路相连(0也被认为是偶数)。不过,由于时间过于久远,具体的交通网络我们已经无法得知了。小宇很好奇这n个城市之间究竟有多少种可能的连接方法,于是她向你求助。

方法数可能很大,你只需要输出方法数模1000000007后的结果。

Input

输入共一行,为3个整数n,m,K。

Output

输出1个整数,表示方案数模1000000007后的结果。

Sample Input

【输入样例1】

3 4 1

【输入样例2】

4 3 3

Sample Output

【输出样例1】

3

【输出样例2】

4

【数据规模】

HINT

100%的数据满足1<= n <= 30, 0 <= m <= 30, 1 <= K <= 8.

【题目说明】

两种可能的连接方法不同当且仅当存在一对城市,它们间的道路数在两种方法中不同。

在交通网络中,有可能存在两个城市无法互相到达。

题目说要取模,通常会这样的有数论或dp。所以虽然数据范围较小,想到搜索的简直233

有两维很好想到,及处理到第i个点,建了j条路的方案数。但是这道题的条件很苛刻,不仅距离不能超过k,还要求所有的点都有偶数条边连接。如果只有距离限制,其实还好处理。然而奇偶性该如何处理?

平时的状压我们认为是选与不选的状态,但是这里算是要开眼界了。只要是两种对立态,就可以用01表示。所以多增一维,记录i与i前面的k个点的奇偶。

然后怎么转移呢?

首先,如果要让我们来建路,我们会枚举每一个点,然后向前面的点建边。所以对于f[i][j][s],我们就考虑i向前k个点连边。

当时我并没有想清楚,去搜题解,于是……

“第一眼看到题比较裸的状压dp就是f[i][j][s]表示考虑到第i个点,连了j条边,i和i左边k个点奇偶性状态为s的方案数,然后枚举i和谁连边向j+1转移,每个s再向i+1转移。

  写完后发现这个做法有bug,因为同一个状态因为i向外连边的顺序不同而被重复记数了。比如:



第一个状态就在第四个状态中被重复记了两次,所以我们在加一位状态l,表示i正准备和i-l连边,这样i的边就是从左往右连的,就不会重复记数了。”——SD_le

于是我想都没想,就多加了一维l

于是状态转移就变成了(->表示做贡献,这是顺推的方式)

f[i][j][s][l]->f[i][j][s][l+1]



f[i][j][s][l]->f[i][j+1][s^(1 << l )^1][l]

这是该解法的完整代码:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. const int mod=1000000007;
  6. int N,M,K;
  7. int f[35][35][1<<10][10];
  8. int main(){
  9. scanf("%d%d%d",&N,&M,&K);
  10. f[1][0][0][0]=1;
  11. for(int i=1;i<=N;i++){
  12. for(int j=0;j<=M;j++){
  13. for(int k=0;k<(1<<(K+1));k++){
  14. for(int l=min(K,i-1);l>=1;l--){
  15. int tmp=f[i][j][k][l];
  16. f[i][j][k][l-1]+=tmp%=mod;
  17. f[i][j+1][k^(1<<l)^1][l]+=tmp%=mod;
  18. }
  19. if(((k>>K)&1)==0) f[i+1][j][(k<<1)&((1<<(N+1))-1)][min(K,i)]+=f[i][j][k][0]%=mod;
  20. }
  21. }
  22. }
  23. printf("%d\n",f[N][M][0][0]);
  24. return 0;
  25. }

然后手贱看了一下rank,发现doggu神名列前茅(前三名打表)。于是前去请教

我们发现,其实第4维l是无用的。为什么会出现上文说到的bug呢?因为我们把建边的顺序更改了一下,造成了重复计算,如果我们直接强制规定建边顺序,就可以减少一维。

被doggu神改的一塌糊涂的三维做法:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. const int MOD=1000000007;
  6. int N,M,K;
  7. int f[2][35][1<<9], cur, pow[9], lim, lm;
  8. inline void add(int &a,int b) {a=a-MOD+b>0?a-MOD+b:a+b;}
  9. int main(){
  10. scanf("%d%d%d",&N,&M,&K);lm=1<<K;lim=1<<(K+1);
  11. f[cur][0][0]=1;
  12. pow[0]=1;
  13. for( int i = 1; i <= K; i++ ) pow[i]=pow[i-1]<<1;
  14. for(int i=1,l,j,k,st,sta;i<=N;i++){
  15. cur^=1;memset(f[cur],0,sizeof(f[cur]));
  16. for( j = 0; j <= M; j++ )
  17. for( st = 0, sta = 0; st < lm; st++, sta+=2 )
  18. f[cur][j][sta]=f[cur^1][j][st];
  19. for(l=min(K,i-1);l>=1;l--)
  20. for(j=0;j<=M;j++)
  21. for(k=0;k<lim;k++)
  22. add(f[cur][j+1][k^pow[l]^1],f[cur][j][k]);
  23. }
  24. printf("%d\n",f[cur][M][0]);
  25. return 0;
  26. }

【bzoj3195】【 [Jxoi2012]奇怪的道路】另类压缩的状压dp好题的更多相关文章

  1. [BZOJ3195][Jxoi2012]奇怪的道路

    3195: [Jxoi2012]奇怪的道路 Time Limit: 10 Sec  Memory Limit: 128 MB Description 小宇从历史书上了解到一个古老的文明.这个文明在各个 ...

  2. 状态压缩动态规划 状压DP

    总述 状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式 很多棋盘问题都运用到了状压,同时,状压也很经常和BFS及DP连用,例题里会给出介绍 有了状态,DP就比 ...

  3. 状态压缩动态规划(状压DP)详解

    0 引子 不要999,也不要888,只要288,只要288,状压DP带回家.你买不了上当,买不了欺骗.它可以当搜索,也可以卡常数,还可以装B,方式多样,随心搭配,自由多变,一定符合你的口味! 在计算机 ...

  4. bzoj3195: [Jxoi2012]奇怪的道路(状压dp)

    Description 小宇从历史书上了解到一个古老的文明.这个文明在各个方面高度发达,交通方面也不例外.考古学家已经知道,这个文明在全盛时期有n座城市,编号为1..n.m条道路连接在这些城市之间,每 ...

  5. BZOJ3195: [Jxoi2012]奇怪的道路【状压DP】

    Description 小宇从历史书上了解到一个古老的文明.这个文明在各个方面高度发达,交通方面也不例外.考古学家已经知道,这个文明在全盛时期有n座城市,编号为1..n.m条道路连接在这些城市之间,每 ...

  6. 2018.10.24 bzoj3195: [Jxoi2012]奇怪的道路(状压dp)

    传送门 f[i][j][k]f[i][j][k]f[i][j][k]表示前iii个点连了jjj条边,第i−K+1i-K+1i−K+1~iii个点连边数的奇偶性为kkk时的方案数. 转移规定只能从后向前 ...

  7. bzoj3195 [Jxoi2012]奇怪的道路——状压DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3195 看到数据范围就应该想到状压呢... 题解(原来是这样):https://www.cnb ...

  8. hihoCoder 1044 : 状态压缩·一 状压dp

    思路:状态压缩,dp(i, j)表示考虑前i个数且[i-m+1, i]的选择情况为j.如果要选择当前这个数并且,数位1的个数不超过q,则dp[i+1][nex] = max(dp[i+1][nex], ...

  9. hihocoder #1044 : 状态压缩·一 状压DP

    http://hihocoder.com/problemset/problem/1044 可以看出来每一位的选取只与前m位有关,我们把每个位置起始的前m位选取状态看出01序列,就可以作为一个数字来存储 ...

随机推荐

  1. keras recall

    # accuracy, fmeasure, precision,recall def mcor(y_true, y_pred): y_pred_pos = K.round(K.clip(y_pred, ...

  2. docker安装tomcat&部署javaweb程序

    一.docker定制简单的java-web应用镜像 网址: 1.jdk下载网址:https://www.oracle.com/technetwork/java/javase/downloads/jdk ...

  3. Centos7安装protobuf3.6.1

    简介 最近学习go语言,需要安装protobuf,但是网上的教程很多都不太适用于centos7 的系统.现在总结下protobuf在centos7下的安装教程. protobuf是Google开发出来 ...

  4. spring -boot定时任务 quartz 基于 JobDetailFactoryBean实现

    这个有点小问题 尚未解决  后期优化 基于 JobDetailFactoryBean实现 依赖包 <dependencies> <dependency> <groupId ...

  5. “EndExecuteNonQuery”方法没有任何重载采用“0”个参数

    EndExecuteNonQuery需要参数IAsyncResult asyncResult myCmd.ExecuteNonQuery();//执行 ExecuteNonQuery 返回受影响行数

  6. Marked Ancestor

    一道并查集的题目硬是被我当成线段树写了,感觉这样写虽然不是最好的,不过能a就行 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=103906 ...

  7. 【Linux命令】解压相关命令

    xxx.tar.gz   :   tar xvzf xxx.tar.gz xxx.tar.bz2 :   tar -vxjf   xxx.tar.bz2

  8. Mysql 5.7存储过程的学习

    存储过程:对sql的封装和重用,经编译创建并保存在数据库中,通过指定存储过程的名字并给定参数(需要时)来调用执行. 优缺点: (1) 优点: 执行速度快------存储过程只在创建时进行编译,以后每次 ...

  9. read、readline 和 readlines 的区别?

    假设a.txt的内容如下所示: 1 Hello 2 Welcome 3 What is the fuck... read:读取整个文件. read([size])方法从文件当前位置起读取size个字节 ...

  10. wpf中文本框只能输入整数

    private void txtBarCodeNum_KeyUp(object sender, KeyEventArgs e) { TxtInt(sender as TextBox); } priva ...