CH 30 摆花 [动态规划] [矩阵快速幂优化]

来源:互联网 发布:it猎头 编辑:程序博客网 时间:2024/05/16 23:56

czy的后宫(harem.cpp/c/pas)
【题目描述】
czy要妥善安排他的后宫,他想在机房摆一群妹子,一共有n个位置排成一排,每个位置可以摆妹子也可以不摆妹子。有些类型妹子如果摆在相邻的位置(隔着一个空的位置不算相邻),就不好看了。假定每种妹子数量无限,求摆妹子的方案数。
【输入格式】
输入有m+1行,第一行有两个用空格隔开的正整数n、m,m表示妹子的种类数。接下来的m行,每行有m个字符1或0,若第i行第j列为1,则表示第i种妹子第j种妹子不能排在相邻的位置,输入保证对称。(提示:同一种妹子可能不能排在相邻位置)。
【输出格式】
输出只有一个整数,为方案数(这个数字可能很大,请输出方案数除以1000000007的余数。
【样例输入】
2 2
01
10
【样例输出】
7
【样例说明】
七种方案为(空,空)、(空,1)、(1、空)、(2、空)、(空、2)、(1,1)、(2,2)。
【数据范围】
20%的数据,1<n≤5,0<m≤10。
60%的数据,1<n≤200,0<m≤100。
100%的数据,1<n≤1000000000,0<m≤100。


首先dp很好想,和之前的统计字符串扩展所表示的数一样。。
但是n<=1e9,那么就用快速幂加速转移。。

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<vector>#include<queue>#include<stack>#include<map>#include<set>#include<string>#include<iomanip>#include<ctime>#include<climits>#include<cctype>#include<algorithm>#ifdef WIN32#define AUTO "%I64d"#else#define AUTO "%lld"#endifusing namespace std;#define smax(x,tmp) x=max((x),(tmp))#define smin(x,tmp) x=min((x),(tmp))#define maxx(x1,x2,x3) max(max(x1,x2),x3)#define minn(x1,x2,x3) min(min(x1,x2),x3)typedef long long LL;const int INF=0x3f3f3f3f;const int mod = 1000000007;const int maxm = 105;int n,m;struct Matrix{    int w[maxm][maxm];    Matrix() { memset(w,0,sizeof(w)); }    Matrix operator * (const Matrix b)    {        Matrix c;        for(int i=0;i<=m;i++)            for(int j=0;j<=m;j++)                for(int k=0;k<=m;k++)                    c.w[i][j]+=(LL)w[i][k]*b.w[k][j]%mod,c.w[i][j]%=mod;        return c;    }}orig,delta;void quick_exp(Matrix a,int p,Matrix &to){    while(p)    {        if(p&1) to=a*to;        a=a*a;        p>>=1;    }}inline void init(){    scanf("%d%d",&n,&m);    char ch=getchar();    for(int i=1;i<=m;i++)        for(int j=1;j<=m;j++)        {            while(!isdigit(ch)) ch=getchar();            delta.w[i][j]=(ch=='0');            ch=getchar();        }    for(int i=0;i<=m;i++) delta.w[i][0]=delta.w[0][i]=1;}int main(){    freopen("harem.in","r",stdin);    freopen("harem.out","w",stdout);    init();    orig.w[0][1]=1;    quick_exp(delta,n,orig);    int ans = 0;    for(int i=0;i<=m;i++) ans+=orig.w[i][1],ans%=mod;    printf("%d",ans);    return 0;}
0 0