procedure2012
It's not worth it to know you're not worth it!

[关键字]:数学 矩阵乘法

[题目大意]:有n个车站,k路车。每个车站只能被一路车停,且同一路车的相邻的两站之间不能超过p,求方案数。

//===============================================================================================================================

[分析]:首先因为同一路车的相邻的两站之间不能超过p,所以除前k个每p车站内都要有所有的公交车。这样可以p个p个的转移,用状态压缩dp,p中第一位必须被一辆车占所以方案数一共有c(9,4)=126个。首先处理出所有的合法状态,将这些状态之间的转移构造成矩阵,然后利用矩阵乘法优化加速。

[代码]:

View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int MOD=30031;

struct node
{
    int n,m;
    int dat[131][131];
    friend node operator * (node a,node b)
    {
        node c;
        c.n=a.n,c.m=b.m;
        memset(c.dat,0,sizeof(c.dat));
        for (int i=1;i<=a.n;++i)
            for (int j=1;j<=b.m;++j)
                for (int k=1;k<=a.m;++k)
                    c.dat[i][j]=(c.dat[i][j]+a.dat[i][k]*b.dat[k][j])%MOD;
        return c;
    }
}ans,g;
int n,k,p,x,y,sum;
int a[131],b[1200];

bool Cleck(int x)
{
    int sum=0;
    while (x)
    {
        if (x%2) ++sum; 
        x/=2;
    }
    return sum==k;
}

void Make()
{
    g.n=sum,g.m=sum;
    for (int i=1;i<=sum;++i)
    {
        int z=x&(a[i]<<1);
        for (int j=1;j<=p;++j)
            if (!((z>>(j-1))&1) && (z+(1<<(j-1)))>=y)
                ++g.dat[i][b[z+(1<<(j-1))]];
    }
}

void Init()
{
    scanf("%d%d%d",&n,&k,&p);
    x=(1<<p)-1,y=1<<(p-1);
    for (int i=0;i<y;++i)
        if (Cleck(y+i)) a[++sum]=y+i,b[y+i]=sum;
    /*for (int i=1;i<=sum;++i)
        printf("%d\n",a[i]);*/
    Make();
    /*for (int i=1;i<=sum;++i)
    {
        for (int j=1;j<=sum;++j)
            printf("%d ",g.dat[i][j]);
        printf("\n");
    }*/
}

void Solve()
{
    int z=b[((1<<k)-1)<<(p-k)];
    //printf("%d\n",z);
    ans.n=1,ans.m=sum;
    ans.dat[1][z]=1;
    n-=k;
    while (1)
    {
        if (n&1) ans=ans*g;
        n>>=1;if (!n) break;
        g=g*g;
    }
    printf("%d\n",ans.dat[1][z]);
}

int main()
{
    Init();
    Solve();
    return 0;
}
posted on 2012-04-18 16:24  procedure2012  阅读(335)  评论(0编辑  收藏  举报