把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

题解 P3204 [HNOI2010] 公交线路

传送门

题意

显然。

分析

我们首先需要观察的就是我们的数据范围:$N\le 10^9$,$P\le10$,$K\le 8$。非常优秀的一个数据范围,我们马上可以筛选我们的算法,主体肯定有一个类倍增的算法加速转移,而转移有极大可能是通过状压来解决。

首先可以想到这样一个状态:$f_{i,j}$ 表示当前来到第 $i$ 个车站,当前仍然停留有车的车站(显然使用状压,因为我们的 $P$ 很小,我们可以用类似滚动数组的方式处理我们的状态)。

接下来解决一下转移。

由于我们题面的一个性质:$1$ 到 $K$ 号站作为始发站,$N-K+1$ 到 $N$ 号台作为终点站。因此我们的过程中,车辆总数是始终为 $k$ 的,这是一个小小的优化,也是转移的关键。

分为两种转移:

  1. 假如说边界上有车,那么这辆车必须,并且只能是这两者转移到 $i$。
  2. 假如说没有,那么我们可以从前边任意一辆车开过来。

可以得到这样的代码:

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]);
            }
        }
    }
}
posted @ 2023-09-19 21:54  djh0314  阅读(35)  评论(0)    收藏  举报  来源
浏览器标题切换
浏览器标题切换end