题面传送门

傻逼卡常屑题/bs/bs,大概现场过得人比较少的原因就是它比较卡常罢(Fog

首先对于这样的题我们很难直接维护,不过注意到这个 \(n=300\) 给得很灵性,\(k\) 比较小和 \(k\) 比较大时各有自己的优势。因此考虑进行数据分治,也就是我们设一个阈值 \(B\),那么对于 \(k\le B\) 的情况是相对来说比较容易的,就设一个 \(dp_{i,S}\) 表示考虑到第 \(i\) 个位置,过去 \(k\) 个位置选择/不选择的状态为 \(S\) 的美丽程度之和,转移就枚举下一个位置选/不选即可实现 \(\mathcal O(1)\) 转移,时间复杂度 \(n2^B\)。

对于 \(k>B\) 的情况,我们考虑将序列想象成一个 \(\lceil\dfrac{n}{k}\rceil\) 行 \(k\) 列的矩阵,第 \(i\) 行包含了 \([(i-1)k+1,ik]\) 位置上的值(如果超过了 \(n\) 就在后面补 \(0\)),那么本题的限制等价于不能同时选择矩阵中相邻的元素,并且对于所有 \(1\le i<\lceil\dfrac{n}{k}\rceil\),第 \(i\) 行最后一个元素和第 \(i+1\) 行第一个元素不能同时被选择,那么如果说之前 \(k\le B\) 的情况是按行状压,那么 \(k>B\) 的情况也就自然可以想到按列状压了,不过由于本题对于第一列与最后一列还有额外的限制,因此考虑首先枚举第一列选择/不选择的状态,然后记 \(dp_{i,S}\) 表示考虑到第 \(i\) 列,第 \(i\) 列选择/不选择的状态为 \(S\) 的所有方案的美丽程度之和,转移就枚举下一列的状态即可,时间复杂度 \(\mathcal O(n8^{n/B})\)。

考虑优化,首先如果直接按照上面的做法做那直接 T 飞——不论你 \(B\) 取啥值。不过注意到对于这一类状压 \(dp\),合法的状态数通常是比较少的,如果你手比较勤快打个表也能发现 \([0,2^k-1]\) 中不存在二进制下不存在两个相邻的 \(1\) 的数恰有 \(Fib_{k+2}\) 个,因此可以直接一遍将符合条件的数筛出来,那么复杂度就降到了 \(nFib_{B+2}\) 和 \(n·Fib_{n/B+2}^3\),不过还是过不去。注意到对于 \(k\) 比较小的暴力已经没啥优化的空间了,因此考虑优化 \(k\) 比较大的暴力,首先我们枚举下一列的状态时候答案的贡献可以预处理出来,这样 \(n·Fib_{n/B+2}^3\) 就降到了 \(k·Fib_{n/B+2}^3\),其次对于两个合法状态 \(j,k\),满足 \(j\&k=0\) 的 \((j,k)\) 数量是小于 \(Fib_{n/B+2}^2\) 的,大约是 \(Fib_{n/B+2}^2\) 的一半,因此考虑将这个东西进一步预处理出来,这样常数就可以小一半。

实测 \(B=25\) 时复杂度最优,\(k\le 25\) 部分复杂度大约是 \(300·3\times 10^5=9\times 10^7\),\(k>25\) 部分复杂度大概是 \(377·26·47321=4\times 10^8\),不过对于 \(n=300,k=25\) 和 \(n=300,k=26\),我的程序似乎都只跑了 1.5s?话说回来由于这题出题人没有把数据卡满,因此这样的复杂度可以通过此题。否则肯定直接 T 飞。

所以说,下次看到 \(200,300\) 这样的数据范围,不要再拘泥地想什么 \(n^3,n^2\log n\) 了,有时候数据分治/根号分治+状压 \(dp\) 也可以出到类似的数据范围。

最后我稍微说一句,赛场上我使用的 vector 预处理合法的状态然后直接 T 飞,\(n=300,k=25\) 的数据跑了 4s,事实上直接每组数据都 \(2^k\) 跑一遍也行。

所以以后别用 vector 了(光速逃

完整代码:(为什么这次要放完整代码呢?因为可以康到三个火车头粘在一起占据程序大部分空间的壮丽景象)

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC target("avx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC target("avx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC target("avx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#pragma comment(linker,"/stack:200000000")
#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
#define y1 y1111111
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){return (!x)?void():(recursive_print(x/10),putc(x%10^48),void());}
template<typename T> void print(T x){(!x)&&(putc('0'),0);(x<0)&&(putc('-'),x=~x+1);recursive_print(x);}
template<typename T> void print(T x,char c){(!x)&&(putc('0'),0);(x<0)&&(putc('-'),x=~x+1);recursive_print(x);putc(c);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=300;
const int MOD=1e9+7;
int n,k,w[MAXN+5];
namespace sub1{
const int MAX=3e5;
int st[MAX+5],rid[(1<<25)+5],lim=0;
int dp[2][MAX+5];
void solve(){
lim=0;
for(int i=0;i<(1<<k);i++) (!(i&(i<<1)))?(st[++lim]=i,rid[i]=lim):rid[i]=0;
for(int j=1;j<=lim;j++) dp[0][j]=dp[1][j]=0;
dp[0][rid[0]]=1;int pre=0,nxt=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=lim;j++) dp[nxt][j]=0;
for(int j=1;j<=lim;j++) if(dp[pre][j]){
int s=st[j],t=(s<<1)&((1<<k)-1);(dp[nxt][rid[t]]+=dp[pre][j])%=MOD;
if((~s&1)&&(~s>>(k-1)&1)) (dp[nxt][rid[t|1]]+=1ll*dp[pre][j]*w[i]%MOD)%=MOD;
} swap(pre,nxt);
} int ans=0;for(int i=1;i<=lim;i++) (ans+=dp[pre][i])%=MOD;
printf("%d\n",(ans-1+MOD)%MOD);
}
}
namespace sub2{
const int MAX=1e3;
int st[MAX+5],rid[(1<<12)+5];
int dp[MAXN+5][MAX+5],mul[MAXN+5][MAX+5],lim=0;
int can[MAX+5][MAX+5];
void solve(){
int bt=n/k+1,ans=0;lim=0;
for(int i=0;i<(1<<bt);i++) (!(i&(i<<1)))?(st[++lim]=i,rid[i]=lim):rid[i]=0;
for(int i=1;i<=k;i++) for(int j=1;j<=lim;j++) mul[i][j]=0;
for(int i=1;i<=k;i++) for(int j=1;j<=lim;j++){
int s=st[j];
if(n/k*k+i>n&&(s>>(bt-1)&1)) continue;
mul[i][j]=1;
for(int l=0;l<bt;l++) if(s>>l&1)
mul[i][j]=1ll*mul[i][j]*w[l*k+i]%MOD;
}
for(int i=1;i<=lim;i++) can[i][0]=0;
for(int i=1;i<=lim;i++) for(int j=1;j<=lim;j++)
if(!(st[i]&st[j])) can[i][++can[i][0]]=j;
for(int i=1;i<=lim;i++){
// printf("%d\n",i);
int s=st[i];
if(n/k*k+k>n&&(s>>(bt-1)&1)) continue;
for(int j=1;j<=k;j++) for(int l=1;l<=lim;l++) dp[j][l]=0;
dp[k][i]=mul[k][i];
for(int j=k;j>=2;j--) for(int l=1;l<=lim;l++) if(dp[j][l]){
for(int o=1;o<=can[l][0];o++)
(dp[j-1][can[l][o]]+=1ll*mul[j-1][can[l][o]]*dp[j][l]%MOD)%=MOD;
} for(int l=1;l<=lim;l++) if(!(st[l]&(s<<1))) (ans+=dp[1][l])%=MOD;
} printf("%d\n",(ans-1+MOD)%MOD);
}
}
void solve(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
if(n<=100) (k<=15)?sub1::solve():sub2::solve();
else (k<=25)?sub1::solve():sub2::solve();
}
int main(){
int qu;scanf("%d",&qu);
while(qu--) solve();
return 0;
}

HDU 6984 - Tree Planting(数据分治+状压 dp)的更多相关文章

  1. HDU 5067 Harry And Dig Machine(状压DP)(TSP问题)

    题目地址:pid=5067">HDU 5067 经典的TSP旅行商问题模型. 状压DP. 先分别预处理出来每两个石子堆的距离.然后将题目转化成10个城市每一个城市至少经过一次的最短时间 ...

  2. HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]

    题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...

  3. HDU 4917 Permutation(拓扑排序 + 状压DP + 组合数)

    题目链接 Permutation 题目大意:给出n,和m个关系,每个关系为ai必须排在bi的前面,求符合要求的n的全排列的个数. 数据规模为n <= 40,m <= 20. 直接状压DP空 ...

  4. HDU 1074:Doing Homework(状压DP)

    http://acm.hdu.edu.cn/showproblem.php?pid=1074 Doing Homework Problem Description Ignatius has just ...

  5. hdu 2167 方格取数 【状压dp】(经典)

    <题目链接> 题目大意: 给出一些数字组成的n*n阶矩阵,这些数字都在[10,99]内,并且这个矩阵的  3<=n<=15,从这个矩阵中随机取出一些数字,在取完某个数字后,该数 ...

  6. HDU 6149 Valley Numer II(状压DP)

    题目链接 HDU6149 百度之星复赛的题目……比赛的时候并没有做出来. 由于低点只有15个,所以我们可以考虑状压DP. 利用01背包的思想,依次考虑每个低点,然后枚举每个状态. 在每个状态里面任意枚 ...

  7. HDU 2809 God of War (状压DP)

    God of War Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  8. HDU 4026 Unlock the Cell Phone 状压dp(类似TSP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4026 Unlock the Cell Phone Time Limit: 6000/3000 MS ...

  9. HDU 3681 Prison Break 越狱(状压DP,变形)

    题意: 给一个n*m的矩阵,每个格子中有一个大写字母,一个机器人从‘F’出发,拾取所有的开关‘Y’时便能够越狱,但是每走一格需要花费1点能量,部分格子为充电站‘G’,每个电站只能充1次电.而且部分格子 ...

随机推荐

  1. css实现水平-垂直居中的方法

    * 定宽居中: 1.absolute+负margin 2.absolute+margin:auto 3.absolute--calc 4.min-height:100vh + flex + margi ...

  2. 【c++ Prime 学习笔记】目录索引

    第1章 开始 第Ⅰ部分 C++基础 第2章 变量和基本类型 第3章 字符串.向量和数组 第4章 表达式 第5章 语句 第6章 函数 第7章 类 第 Ⅱ 部分 C++标准库 第8章 IO库 第9章 顺序 ...

  3. .Net2.0连接PG数据注意事项

    .Net2.0连接PG数据注意事项 第一次用.net操作PG[.NET2.0] 一:Npgsql版本问题 1:如果是.net2.0  建议用2.0.11.0[NuGet搜索npgsql第一个的最低版本 ...

  4. OO第三次博客作业--第三单元总结

    一.JML 语言的理论基础及应用工具链 JML 是一种行为接口规格语言,提供了对方法和类型的规格定义手段.通过 JML 和其支持工具,不仅可以基于规格自动构造测试用例,并整合了 SMT Solver ...

  5. wifi 热点配置最优信道

    wifi热点服务hostapd启动需要配置hostad.conf文件,其中有一个参数channel是用来配置信道的,信道的可选参数如下: # channel 1-14 is 2.4 GHz ; cha ...

  6. DP秒思维

    DP算法对于大部分题有着良好的能力,但有些题目我们要转换思维,不能直接的设具体的转态.... 最近做了两道秒题,在这里分享一下: https://ac.nowcoder.com/acm/contest ...

  7. Redis源码分析(intset)

    源码版本:4.0.1 源码位置: intset.h:数据结构的定义 intset.c:创建.增删等操作实现 1. 整数集合简介 intset是Redis内存数据结构之一,和之前的 sds. skipl ...

  8. Python之模块导入(不看会后悔系列)

    看到这个标题猜想大家内心OS: 什么辣鸡水文,划走划走~ 别急有干货! 静态导入(照顾新人) 假设现在有两个文件a,b在不同目录,b文件想引用a文件中的函数: # test_module/sub_mo ...

  9. OpenYurt 与 FabEdge 集成验证——云边数据面通信初试

    作者|浙江大学 SEL 实验室:晋晨.博云:耿浩涛 审核&校对:海珠 编辑&排版:雯燕 背景 在近几年的产业环境下,传统云计算能力已无法支撑起规模日趋庞大且异地分散的数据处理与计算需求 ...

  10. Cannot load module file xxx.iml的两种解决方法

    一. 一种是点击左上角File,然后点击Invalidate Caches / Restart...,弹出对话框再点击Invalidate and Restart等待工程重新加载,问题就解决了. 二. ...