zoukankan      html  css  js  c++  java
  • [HNOI2010]公交线路

    [HNOI2010]公交线路

    不看题解不会做类型...
    看到数据范围,显然要构造矩阵.
    但是状态有那么多,于是要缩减状态.
    (dp[i][s])表示第i个车站和之后的p个车站,k辆车最后出没的位置.一辆车最多走p个车站,于是必定会在这p个车站出现至少一次,j就是一个长度为p的,含k个1的01串,最多有252种情况,转移只要在1之间转移就可以了,所以显然第一位没有车的状态可以缩掉.
    每次转移只动一辆车,这样一步一步地走,不重不漏.转移矩阵构出来之后直接快速幂就可以了,最后要的状态是(dp[n-k][(1<<k)-1])

    #include<bits/stdc++.h>
    #define mod 30031
    using namespace std;
    int n,k,p,s,f[20],st[505];
    int lowbit(int x){return x&-x;}
    int calc(int x){int r=0;for(int i=x;i>=1;i-=lowbit(i),r++);return r;}
    struct matrix
    {
        int a[150][150];
        int *operator [] (int i){return a[i];}
        matrix operator * (matrix x)
            {
                matrix y;memset(y.a,0,sizeof(y.a));
                for(int i=1;i<=s;i++)
                    for(int j=1;j<=s;j++)
                        for(int k=1;k<=s;k++)
                            y[i][j]+=a[i][k]*x[k][j]%mod,y[i][j]%=mod;
                return y;
            }
    }A,B;
    void ksm(int k)
    {
        for(int i=1;i<=s;i++)A[i][i]=1;
        while(k){if(k&1)A=A*B;k>>=1;B=B*B;}
    }
    int main()
    {
        cin>>n>>k>>p;//状态记录的是k辆车在i往后p个站点的最后出没点
        for(int i=0;i<(1<<p);i++)//合法状态是第1个位置有车,区间里一定是k个最后出没点
            if(calc(i)==k&&(i&1))st[++s]=i;
        for(int i=1;i<=s;i++)
            for(int j=1;j<=s;j++)
                if(calc((st[i]>>1)&st[j])==k-1)B[i][j]=1;
        ksm(n-k);
        cout<<A[1][1]<<endl;
        return 0;
    }
    
    
  • 相关阅读:
    个人学期总结
    管理信息系统 第三部分 作业
    模型分离(选做)
    密码保护
    实现搜索功能
    完成个人中心—导航标签
    个人中心标签页导航
    评论列表显示及排序,个人中心显示
    完成评论功能
    ASP.NET Core开发者指南
  • 原文地址:https://www.cnblogs.com/terribleterrible/p/9833630.html
Copyright © 2011-2022 走看看