题解 P3204 [HNOI2010] 公交线路
传送门。
题意
显然。
分析
我们首先需要观察的就是我们的数据范围:$N\le 10^9$,$P\le10$,$K\le 8$。非常优秀的一个数据范围,我们马上可以筛选我们的算法,主体肯定有一个类倍增的算法加速转移,而转移有极大可能是通过状压来解决。
首先可以想到这样一个状态:$f_{i,j}$ 表示当前来到第 $i$ 个车站,当前仍然停留有车的车站(显然使用状压,因为我们的 $P$ 很小,我们可以用类似滚动数组的方式处理我们的状态)。
接下来解决一下转移。
由于我们题面的一个性质:$1$ 到 $K$ 号站作为始发站,$N-K+1$ 到 $N$ 号台作为终点站。因此我们的过程中,车辆总数是始终为 $k$ 的,这是一个小小的优化,也是转移的关键。
分为两种转移:
- 假如说边界上有车,那么这辆车必须,并且只能是这两者转移到 $i$。
- 假如说没有,那么我们可以从前边任意一辆车开过来。
可以得到这样的代码:
for(int i=m; i<n; ++i) {
for(int j=0; j<=up; ++j) {
if(cnt[j]!=m) continue;//m即k
if(j&(1<<P-1)) f[i+1][(j<<1|1)&up]=(f[i+1][(j<<1|1)&up]+f[i][j])%MOD;
else {
for(int k=0; k<P-1; ++k) {
if((1<<k)&j) {
int st=j^(1<<k);
f[i+1][st<<1|1]=(f[i+1][st<<1|1]+f[i][j])%MOD;
}
}
}
}
}
我们后面的代码万变不离其宗,所以这一段代码一定要理解。
此时我们发现,可以拿到 $40pts$,时间复杂度:$O(n\times K\times w^P)$,($w=2$),在空间与与时间上都受到限制。
紧接着,尝试优化我们的转移,首先就是最直白的,使用矩阵快速幂优化。
此处的代码大同小异,只是将原来的转移方式转化成矩阵上的节点 $+1$ 即可。由于数据上的特殊,我们的优化并没有效果,反而只能拿到 $10pts$,时间复杂度:$O(\log n\times w^{3\times P})$。
接下来我们就需要思考优化我们的转移。
首先上面提及的那个特征:过程中,车辆总数是始终为 $k$ 的,所以,我们的有用的节点实际只有 $C_{P}^{K} $ 个,即最大只有 $C_{10}^{5}=252 $ 个,可以使用一个 map 来进行离散化,现在我们就可以拿到 $80$ 的高分。
继续考虑优化我们的有用个数,又可以观察到,我们的状态实际上第 $0$ 位绝对是 1,又可以优化掉一位,拿下 $100pts$。
int up=(1<<P)-1,cnt_m=0;
for(int i=1; i<=up; ++i) {
cnt[i]=cnt[i-lowbit(i)]+1;
if(cnt[i]==m&&(i&1)) ma[i>>1]=cnt_m++;
}
ans.n=1,ans.m=bas.n=bas.m=cnt_m;
ans.a[0][ma[((1<<m)-1)>>1]]=1;
for(int j=0; j<=up; ++j) {
if(cnt[j]!=m||(j&1)==0) continue;
if(j&(1<<P-1)) {
add(bas,ma[j>>1],ma[((j<<1|1)&up)>>1]);
} else {
for(int k=0; k<P-1; ++k) {
if((1<<k)&j) {
int st=j^(1<<k);
add(bas,ma[j>>1],ma[(st<<1|1)>>1]);
}
}
}
}

浙公网安备 33010602011771号