czy的后宫——矩阵快速幂优化DP

题意

有 n 个位置排成一行,可以放 m 种妹子。每个位置可以放也可以不放,规定某些妹子不能相邻,求方案数。

分析

 

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

ll qmul(ll x,ll y,ll p){        //快速乘
    x%=p;
    y%=p;
    ll ans=0;
    while(y){
        if(y&1){
            ans+=x;
            if(ans>=p) ans-=p;  //这样写不能有负数
        }
        x<<=1;
        if(x>=p) x-=p;
        y>>=1;
    }
    return ans;
}

struct Mat{
    int r,c;
    ll m[110][110];
    Mat(){
        memset(m,0,sizeof(m));
    }
};

Mat mmul(Mat x,Mat y,ll p){
    Mat ans;
    ans.r=x.r;
    ans.c=y.c;
    for(int i=0;i<x.r;i++)
        for(int k=0;k<x.c;k++)
            for(int j=0;j<y.c;j++){
                ans.m[i][j]+=qmul(x.m[i][k],y.m[k][j],p);
                if(ans.m[i][j]>=p) ans.m[i][j]-=p;
            }
    return ans;
}
Mat mpow(Mat x,ll y,ll p){
    Mat ans;
    ans.r=x.r;
    ans.c=x.c;
    for(int i=0;i<ans.c;i++) ans.m[i][i]=1;
    while(y){
        if(y&1) ans=mmul(ans,x,p);
        x=mmul(x,x,p);
        y>>=1;
    }
    return ans;
}

const ll mod = 1000000007;
Mat T, A;
int n, m;
char s[110];


int main(){
    scanf("%d%d", &n, &m);
    T.r = T.c = m+1;
    for(int i = 0;i < m;i++)
    {
        scanf("%s", s);
        for(int j = 0;j < m;j++)
            T.m[i][j] = 1- (s[j] - '0');
        T.m[i][m] =  1;
    }
    for(int i = 0;i <= m;i++)  T.m[m][i] = 1;   //补充一类”空妹子“

    T = mpow(T, n-1, mod);
    A.r = 1, A.c = m+1;
    for(int i = 0;i <= m;i++)  A.m[0][i] = 1;
    A = mmul(A, T, mod);
    ll ans = 0;
    for(int i = 0;i <= m;i++)  ans = (ans + A.m[0][i]) % mod;
    printf("%lld\n", ans);

    return 0;
}

没处交题,只能找别人题解的代码对拍,应该没错吧??

 

 

 

参考链接:https://blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/52745912

 

posted @ 2019-08-11 13:37  Rogn  阅读(383)  评论(0编辑  收藏  举报