Codeforces917C. Pollywog
$n \leq 1e8$个石头,$x \leq 8$个蝌蚪一开始在最左边$x$个石子,要跳到最右的$x$个,每次只能最左边的蝌蚪跳一次,一个石头不能站两个蝌蚪,跳可以跳$1到k,x \leq k \leq 8$步,跳$i$步的代价是$cost_i$,还有$q \leq 25$个神奇石头,跳上去代价会$+w_i$,$w_i$可能为负数。问完成跳跃的最小代价。
不知道跳蝌蚪是什么操作只听过跳蛤,大概是变相膜?
好的严肃。从小数字$x$和$k$入手。由于每次只有最左的蝌蚪会跳,所以这$x$个蝌蚪一定每时每刻都在某连续的$k$个石头上。记这$k$个石头最左的那个(不一定上面有蝌蚪)为$i$,那么$i$处右边$k$个石子上的蝌蚪状态可以用二进制表示,最多是$C_8^4=70$个状态,挺小。这样就可以做转移了,转移复杂度是$C_k^x*k$,再乘个$n$直接爆炸。不过我们来看这个转移,$dp(i,j)=dp(i-1,k)+cost_t$,想到啥了?走若干步的最短路!这是可以用矩乘优化的,于是在不考虑$q$时,可以做$log_2n*(C_k^x)^3$的$dp$。
然后来看$q$。一块神奇石头影响了$k$块地(di)的(de)转移,因此最多会有$q*k$块地受影响,挺小,矩乘到这些地段时停住,暴力转移。最终复杂度$log_2n*(C_k^x)^3+qk^2C_k^x$。
//#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
//#include<map>
#include<math.h>
//#include<time.h>
//#include<complex>
#include<algorithm>
using namespace std; int X,K,n,m,q;
#define LL long long
const LL inf=1e18;
struct Mat
{
LL a[][];
Mat() {for (int i=;i<=;i++) for (int j=;j<=;j++) a[i][j]=inf;}
Mat operator * (const Mat &b)
{
Mat ans;
for (int k=;k<=m;k++)
for (int i=;i<=m;i++)
for (int j=;j<=m;j++)
ans.a[i][j]=min(ans.a[i][j],a[i][k]+b.a[k][j]);
return ans;
}
}base,f; Mat pow(Mat a,int b)
{
Mat ans,tmp=a; for (int i=;i<=m;i++) ans.a[i][i]=;
while (b)
{
if (b&) ans=ans*tmp;
tmp=tmp*tmp; b>>=;
}
return ans;
} int state[],ls,who[];
struct Ran{int l,r;}qq[],ran[]; int len;
LL g[],h[];int cost[];
struct Block{int pos,w;}ww[];
bool cmpww(const Block &a,const Block &b) {return a.pos<b.pos;}
struct Hash
{
int first[],le; struct Edge{int to,v,next;}edge[];
Hash() {le=;}
void insert(int x,int y) {int h=x%; Edge &e=edge[le]; e.to=x; e.v=y; e.next=first[h]; first[h]=le++;}
int find(int x) {int h=x%; for (int i=first[h];i;i=edge[i].next) if (edge[i].to==x) return edge[i].v; return -2e9;}
}ha; int main()
{
scanf("%d%d%d%d",&X,&K,&n,&q);
for (int i=;i<=K;i++) scanf("%d",&cost[i]);
for (int i=;i<=q;i++) scanf("%d%d",&ww[i].pos,&ww[i].w); sort(ww+,ww++q,cmpww);
LL ans=; for (int &i=q;i;i--) if (ww[i].pos>=n-X+) ans+=ww[i].w; else break;
for (int i=;i<=q;i++) ha.insert(ww[i].pos,ww[i].w);
for (int i=;i<=q;i++) qq[i].l=max(ww[i].pos-K,),qq[i].r=ww[i].pos;
len=; for (int i=;i<=q;i++)
{
if (len && qq[i].l<=ran[len].r+) ran[len].r=qq[i].r;
else len++,ran[len].l=qq[i].l,ran[len].r=qq[i].r;
}
ls=; for (int i=;i<(<<K);i++)
{
int cnt=;
for (int j=;j<K;j++) if ((i>>j)&) cnt++;
if (cnt==X) ls++,state[i]=ls,who[ls]=i;
} m=ls;
for (int i=;i<=ls;i++)
{
int s=who[i]>>;
if ((who[i]&)==) base.a[i][state[s]]=;
else for (int j=;j<=K;j++) if (((s>>(j-))&)==) base.a[i][state[s|(<<(j-))]]=cost[j];
}
f.a[][]=; ran[].r=;
for (int i=;i<=len;i++)
{
f=f*pow(base,ran[i].l-ran[i-].r-);
for (int j=;j<=ls;j++) g[j]=f.a[][j];
for (int j=ran[i].l;j<=ran[i].r;j++)
{
for (int k=;k<=ls;k++) h[k]=inf;
for (int k=;k<=ls;k++)
{
int s=who[k]>>;
if ((who[k]&)==) h[state[s]]=min(h[state[s]],g[k]);
else for (int l=,tmp;l<=K;l++) if (((s>>(l-))&)==)
{
int ns=s|(<<(l-));
if ((tmp=ha.find(j+l-))!=-2e9) h[state[ns]]=min(h[state[ns]],g[k]+cost[l]+tmp);
else h[state[ns]]=min(h[state[ns]],g[k]+cost[l]);
}
}
for (int k=;k<=ls;k++) g[k]=h[k];
}
for (int j=;j<=ls;j++) f.a[][j]=g[j];
}
f=f*pow(base,n-X+-ran[len].r);
printf("%lld\n",ans+f.a[][]);
return ;
}
Codeforces917C. Pollywog的更多相关文章
- CF917C Pollywog —— 状压DP + 矩乘优化
C. Pollywog 题目描述 原题题目链接.题目大意为:有$x$只蝌蚪,在$n$个石头中的最左端的$x$个石头上,这$n$个石头是在同一直线上的.每一次只能最左边的一个蝌蚪进行跳跃,并且只能跳$1 ...
- Codeforces 917C - Pollywog(状压 dp+矩阵优化)
UPD 2021.4.9:修了个 typo,为啥写题解老出现 typo 啊( Codeforces 题目传送门 & 洛谷题目传送门 这是一道 *2900 的 D1C,不过还是被我想出来了 u1 ...
- Pollywog CodeForces - 917C (状压)
链接 大意: 一共n个格子, 初始$x$只蝌蚪在前$x$个格子, 每次最左侧的蝌蚪向前跳, 跳跃距离在范围[1,k], 并且每只蝌蚪跳跃都有一定花费, 有$q$个格子上有石头, 若有蝌蚪跳到某块石头上 ...
随机推荐
- var、符号运算、条件语句、三元(目)运算、自加和自减
1.var a=“hello world” a 这个变量是字符串了,对于里面的每一个字母来说,他是字节,里面有11个字节,(包括空格),字节总数用length表示 2.符号运算 + 字符串拼接 . ...
- iOS 动画(基于Lottie封装)
一般app中都会带有动画,而如果是一些复杂的动画,不但实现成本比较高,而且实现效果可能还不能达到UI想要的效果,于是我们可以借助lottie来完成我们想要的动画. lottie动画1.gif ...
- 应用-如何使不同的企业使用独自的数据源。使用ejb3.0+jboss6.2EAP+JPA
摘要: 如何使不同的企业使用独自的数据源.使用ejb3.0+jboss6.2EAP+JPA10C应用系统被多个企业同时使用,为了提供个性化服务,如何使不同的企业使用独自的 ...
- 洛谷 P1216 [USACO1.5]数字三角形 Number Triangles(水题日常)
题目描述 观察下面的数字金字塔. 写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大.每一步可以走到左下方的点也可以到达右下方的点. 7 3 8 8 1 0 2 7 4 4 4 5 ...
- IOS中经典的缓存对比
http://bpoplauschi.wordpress.com/2014/03/21/ios-image-caching-sdwebimage-vs-fastimage/
- 一个SAP开发人员的双截棍之路
由于种种原因,Jerry最近加入了SAP成都研究院的一个演讲俱乐部,这个俱乐部主要是提高大家的英语演讲能力. 说来Jerry也是大一下期和大二上期一次性高分通过四六级考试的,但是当毕业进入SAP成都研 ...
- centos7 设置grub密码及单用户登录实例
centos7与centos6在设置grub密码的操作步骤上有很大的差别,特此记录供以后查用 grub加密的目的: 防止不法分子利用单用户模式修改root密码 给grub加密可以采用明文或者加密的密文 ...
- 基础数据类型(set集合)
认识集合 由一个或多个确定的元素所构成的整体叫做集合. 集合中的元素有三个特征: 1.确定性(集合中的元素必须是确定的) 2.互异性(集合中的元素互不相同.例如:集合A={1,a},则a不能等于1) ...
- 日常:论我的T3是如何苟掉的
说起来都是泪啊 T3的bfs一直不对,我想死. 考试时候苟了两个小时,死活找不到错误(因为lca和离散化都码出来了,太乱) 最后把bfs单独提出来,发现在bfs里面输出的f[ly][0]都是正确的,到 ...
- mysql的sql语句练习的2个网址
sql语句练习: https://blog.csdn.net/mrbcy/article/details/68965271 完成. https://blog.csdn.net/flycat296/ar ...