zoukankan      html  css  js  c++  java
  • BZOJ2004 HNOI2010公交线路(状压dp+矩阵快速幂)

      由数据范围容易想到矩阵快速幂和状压。

      显然若要满足一辆公交车的相邻站台差不超过p,则每相邻p个站台中每辆车至少经过一个站台。可以发现这既是必要的,也是充分的。

      开始的时候所有车是相邻的。考虑每次把一辆公交车塞到前方第一个未到达的站台。这个时候公交车之间是没有区别的,因为只要保证每相邻p个站台每辆车都出现也即有k辆车就可以了。

      于是设f[i][j]为i-p+1~i的车站停靠状况为j的方案数。并且表示i站台状况的这一位必为1,j中一共有k个1。于是状态数至多有C(9,4)=126种。转移比较显然,只要由这个状态开一辆车能到下个状态就可以了。

      每次转移都是相同的,那么矩阵快速幂即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define P 30031
    #define N 130
    struct matrix
    {
        int n,a[N][N];
        matrix operator *(const matrix&b) const
        {
            matrix c;c.n=n;
            for (int i=0;i<n;i++)
                for (int j=0;j<b.n;j++)
                c.a[i][j]=0;
            for (int i=0;i<n;i++)
                for (int j=0;j<b.n;j++)
                    for (int k=0;k<b.n;k++)
                    c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%P;
            return c;
        }
    }f,d;
    int n,k,p,id[N],m;
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj2004.in","r",stdin);
        freopen("bzoj2004.out","w",stdout);
        const char LL[]="%I64d";
    #else
        const char LL[]="%lld";
    #endif
        n=read(),k=read(),p=read();
        for (int i=1<<p-1;i<(1<<p);i++)
        {
            int t=i,cnt=0;
            while (t) cnt+=t&1,t>>=1;
            if (cnt==k) id[m++]=i;
        }
        d.n=m;
        for (int i=0;i<m;i++)
            for (int j=0;j<m;j++)
            {
                int x=(id[j]&(1<<p-1)-1)<<1^id[i];
                if (x==(x&-x)) d.a[i][j]=1;
            }
        f.n=1;
        f.a[0][m-1]=1;
        n-=k;
        while (n)
        {
            if (n&1) f=f*d;
            n>>=1;
            d=d*d;
        }
        cout<<f.a[0][m-1];
        return 0;
    }
  • 相关阅读:
    AutoCompleteTextView 简单用法
    照片颠倒问题及查询摄像头参数问题的解决
    Android Studio-引用jar及so文件
    file新建文件及文件夹
    appcompat_v7报错
    fresco加载本地图片、gif资源
    android根据图片路径显示图片
    sublime text3 及相关的安装
    win 10通过自带IIS搭建ftp
    LCA
  • 原文地址:https://www.cnblogs.com/Gloid/p/9459761.html
Copyright © 2011-2022 走看看