HDU 6984 - Tree Planting(数据分治+状压 dp)
傻逼卡常屑题/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)的更多相关文章
- HDU 5067 Harry And Dig Machine(状压DP)(TSP问题)
题目地址:pid=5067">HDU 5067 经典的TSP旅行商问题模型. 状压DP. 先分别预处理出来每两个石子堆的距离.然后将题目转化成10个城市每一个城市至少经过一次的最短时间 ...
- HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]
题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...
- HDU 4917 Permutation(拓扑排序 + 状压DP + 组合数)
题目链接 Permutation 题目大意:给出n,和m个关系,每个关系为ai必须排在bi的前面,求符合要求的n的全排列的个数. 数据规模为n <= 40,m <= 20. 直接状压DP空 ...
- HDU 1074:Doing Homework(状压DP)
http://acm.hdu.edu.cn/showproblem.php?pid=1074 Doing Homework Problem Description Ignatius has just ...
- hdu 2167 方格取数 【状压dp】(经典)
<题目链接> 题目大意: 给出一些数字组成的n*n阶矩阵,这些数字都在[10,99]内,并且这个矩阵的 3<=n<=15,从这个矩阵中随机取出一些数字,在取完某个数字后,该数 ...
- HDU 6149 Valley Numer II(状压DP)
题目链接 HDU6149 百度之星复赛的题目……比赛的时候并没有做出来. 由于低点只有15个,所以我们可以考虑状压DP. 利用01背包的思想,依次考虑每个低点,然后枚举每个状态. 在每个状态里面任意枚 ...
- HDU 2809 God of War (状压DP)
God of War Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 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 ...
- HDU 3681 Prison Break 越狱(状压DP,变形)
题意: 给一个n*m的矩阵,每个格子中有一个大写字母,一个机器人从‘F’出发,拾取所有的开关‘Y’时便能够越狱,但是每走一格需要花费1点能量,部分格子为充电站‘G’,每个电站只能充1次电.而且部分格子 ...
随机推荐
- 【UE4 C++】定时器 Timer 与事件绑定
概念 定时执行操作,可执行一次,或循环执行直到手动终止 定时器在全局定时器管理器(FTimerManager 类型)中管理.全局定时器管理器存在于 游戏实例 对象上以及每个 场景 中 定时器需要绑定委 ...
- 【UE4 C++】调用外部链接库 lib静态库
简述 本例以插件形式测试 使用Lib引用,打包程序运行不用再拷贝lib文件 需要 lib 文件和 .h 头文件 lib部分的代码 .h 头文件 #pragma once #ifndef __MYTES ...
- .net Xml加密解密操作
生成密钥的方法: /// <summary>生成RSA加密 解密的 密钥 /// 生成的key就是 方法EncryptByRSA与DecryptByRSA用的key了 /// </s ...
- Uniapp云打包生成apk下载链接
使用uni[]()app云打包生成安装包下载链接 manifest.json 中配置自动获取appid manifest.json中配置app 图标 按教程生成.keystore证书 使用云打包生成安 ...
- JAVA实现表达式求导运算的分析总结
1第一次作业 1.1题目描述 对形如4*x+x^2+x的多项式求导. 1.2类图 1.3度量分析 在完成第一次作业时,我的写法没有特别的"面向对象".唯一封装起来的是Node,代表 ...
- STM32中AD采样的三种方法分析
在进行STM32F中AD采样的学习中,我们知道AD采样的方法有多种,按照逻辑程序处理有三种方式,一种是查询模式,一种是中断处理模式,一种是DMA模式.三种方法按照处理复杂方法DMA模式处理模式效率最高 ...
- EFCore_环境搭建与简单使用_01
开发环境搭建 经典步骤:建实体类.建DbContext.生成数据库 本次使用codefirst模式,走下流程,(你也可以先建好数据库,用命令行的形式,直接生成DbContext,而且生成的DbCont ...
- clone-graph leetcode C++
Clone an undirected graph. Each node in the graph contains alabeland a list of itsneighbors. OJ's un ...
- Swift-技巧(四)设置照片尺寸和格式
摘要 平时实现拍照功能时,都是网上一通搜索,整体复制粘贴,自称无脑实现.但是当要求照片是不同的尺寸和格式( JPEG)时,就费力搞照片.其实在设置拍照时,就可以直接设置照片的尺寸和格式,用直接的方法来 ...
- 全面!总结BQ系列阻抗跟踪电量计化学Chemical ID配置和Golden学习方法
BQ系列阻抗跟踪电量计SOC最高能达到1%,功能强大,应用起来也比较复杂.不仅要配置好参数,匹配好化学ID,并且进行好Golden学习和相关测试.本文就讲述ID匹配,Golden学习和测试的终极方法流 ...