现在的位置: 首页 > 综合 > 正文

POJ 3420

2017年11月21日 ⁄ 综合 ⁄ 共 1279字 ⁄ 字号 评论关闭

状态压缩加矩阵。

状态压缩的思想和前面几道状态压缩的题一样的,没的说。但是矩阵为什么可以快速幂非常疑惑不解。。。。。嗯,,因为这道题的数据大,所以要用一个矩阵来递推。

刚开始的时候把记录结果的那个矩阵地对角线给标为一了,现在我认为是因为为了要记录能从pre推到now的状态总数。但是不懂为什么到后来是要相乘。然后不懂为什么每次当k推到奇数的时候才进行记录。。。。

这里先mark一下。

************************************************

诶。。。当初我看矩阵快速幂的时候是有多散漫啊,这次看别人的代码一点没看出来只是一个快速幂,,,还以为里面还有什么玄机。。。。。擦咧。。。。

好忧伤。。。。。。。然后我还没看出来那个对角线是1 的矩阵叫做。。。单位矩阵。。。。呵呵了。。。。

贴代码。。跑了63ms。。。。嗯。。。。

刚开始wa了好多次,,为什么呢呢。。。。谨遵队友指示不敢对拍了,不过第一发现是自己对于矩阵乘法的剪枝还不熟,所以这里用的是纯土法。然后,,,本来我使用n本尊进行快速幂的,然后,,把它换成k来替代就过了,,诶,,,高冷的n。。。

为毛啊。。。

#include <stdio.h>
#include <string.h>
#define ll __int64
int n,m;
struct node
{
    ll a[16][16];
}mat;
void dfs(int d,int now,int pre)
{
    if(d>4) return;
    if(d==4)
    {
        ++mat.a[pre][now];
        return;
    }
    dfs(d+1,now<<1|1,pre<<1);
    dfs(d+1,now<<1,pre<<1|1);
    dfs(d+2,now<<2|3,pre<<2|3);
}
struct node mul(node x,node y)
{
    int i,j,k;
    node z;
    memset(z.a,0,sizeof(z.a));
    for(i=0;i<16;i++)
    {
        for(j=0;j<16;j++)
        {
            for(k=0;k<16;k++)
                z.a[i][j]+=x.a[i][k]*y.a[k][j]%m;
            z.a[i][j]%=m;
        }
    }
    return z;
}
struct node solve(node x)
{
    if(n==1) return x;
    node tmp;
    memset(tmp.a,0,sizeof(tmp.a));
    int i,j,k;
    for(i=0;i<16;i++) tmp.a[i][i]=1;
    k=n;
    while(k)
    {
        if(k&1) tmp=mul(x,tmp);
        x=mul(x,x);
        k>>=1;
    }
    return tmp;
}

int main()
{
    memset(mat.a,0,sizeof(mat.a));
    dfs(0,0,0);
    while(scanf("%d%d",&n,&m)!=EOF&&n+m)
    {
        node ans;
        if(m==1) {printf("0\n");continue;}
        ans=solve(mat);
        printf("%I64d\n",ans.a[15][15]);
    }
    return 0;
}

【上篇】
【下篇】

抱歉!评论已关闭.