码迷,mamicode.com
首页 > 其他好文 > 详细

51nod1730 涂边

时间:2019-09-13 20:25:59      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:宽度   stdin   lld   状态   info   set   namespace   题解   图片   

题目描述

技术图片
技术图片
技术图片
技术图片

题解

八级sb题

显然可以想到状压

枚举当前的宽度\(I\),设\(f[s]\)表示在当前的宽度下选的竖边的状态为s

再设\(g[s1][s2]\)表示状态s1转移到s2的方案数,枚举中间横边的集合s3

显然一个合法的方案中不能存在四边都是边的方格,即\(s1\&s2\&(s3+2^{I-1})\&((s3<<1)+1)\)

如果第i个格子存在四边,那么只能是\(s1\)的第\(i-1\)位(即\(2^{i-1}\))、\(s2\)的第\(i-1\)位、\(s3\)的第\(i-2\)位和第\(i-1\)位都存在,于是就有了上面的式子

dp随便转移,然而这样会挂(

矩乘加速即可

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define mod 1000000007
using namespace std;

int p[8]={0,1,2,4,8,16,32,64};
int w[8];
long long f[2][128];
long long a[128][128];
long long b[128][128];
long long c[128][128];
int i,j,k,l,I,L,i2,i3;

int main()
{
//  freopen("51nod1730.in","r",stdin);
//  freopen("51nod1730.out","w",stdout);
    
    fo(i,1,7)
    scanf("%d",&w[i]);
    
    i2=0;
    f[0][0]=1;
    
    fo(I,1,7)
    {
        i3=i2^1;
        memset(f[i3],0,sizeof(f[i3]));
        
        L=p[I]*2-1;
        fo(i,0,p[I]-1)
        f[i3][i|p[I]]=f[i2][i];
        i2=i3;
        
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        fo(i,0,L)
        {
            fo(j,0,L)
            {
                fo(k,0,p[I]-1)
                if (!(i&j&((k<<1)+1)&(k+p[I])))
                ++b[i][j];
            }
        }
        fo(i,0,L)
        a[i][i]=1;
        
        while (w[I])
        {
            if (w[I]&1)
            {
                memset(c,0,sizeof(c));
                fo(i,0,L)
                {
                    fo(j,0,L)
                    {
                        fo(k,0,L)
                        c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
                    }
                }
                fo(i,0,L)
                {
                    fo(j,0,L)
                    a[i][j]=c[i][j];
                }
            }
            
            memset(c,0,sizeof(c));
            fo(i,0,L)
            {
                fo(j,0,L)
                {
                    fo(k,0,L)
                    c[i][j]=(c[i][j]+b[i][k]*b[k][j])%mod;
                }
            }
            fo(i,0,L)
            {
                fo(j,0,L)
                b[i][j]=c[i][j];
            }
            
            w[I]>>=1;
        }
        
        i3=i2^1;
        memset(f[i3],0,sizeof(f[i3]));
        
        fo(j,0,L)
        {
            fo(k,0,L)
            f[i3][j]=(f[i3][j]+f[i2][k]*a[k][j])%mod;
        }
        i2=i3;
    }
    
    printf("%lld\n",f[i2][p[7]*2-1]);
    
    fclose(stdin);
    fclose(stdout);
    
    return 0;
}

51nod1730 涂边

标签:宽度   stdin   lld   状态   info   set   namespace   题解   图片   

原文地址:https://www.cnblogs.com/gmh77/p/11517312.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!