zoukankan      html  css  js  c++  java
  • Blocks [POJ3734] [矩阵快速幂]

    题意:

    有长度为n的一排格子,每个格子里面可以任意填入1,2,3,4四个数字,问1,2都为偶数个的方案

    T组数据,每组数据一个n(<=1e9)

    样例输入

    2

    1

    2

    样例输出

    2

    6

    分析

    设dp[i][0/1/2/3]分别为处理到第i个,1和2的个数分别为 全偶、1偶2奇、1奇2偶,全奇

    那么dp转移方程为

    dp[i][0]=2dp[i-1][0]+dp[i-1][1]+dp[i-1][2] 填的分别是 3/4 1 2

    dp[i][1]=dp[i-1][0]+2dp[i-1][1]+dp[i-1][3] 填的分别是 2 3/4 1

    dp[i][2]=dp[i-1][0]+2dp[i-1][2]+dp[i-1][3] 填的分别是 1 3/4 2

    dp[i][3]=dp[i-1][1]+dp[i-1][2]+2dp[i-1][3] 填的分别是 1 2 3/4

    我们发现dp[i][1]和dp[i][2]可以合并在一起

    那么将dp[i][1]和dp[i][2]合并为dp[i][1],dp[i][3]改为dp[i][2]

    那么dp转移方程简化为:(简化方式为上面2式和3式相加,dp[i][1]和dp[i][2]替换为dp[i][1],dp[i][3]替换为dp[i][2])

    dp[i][0]=2dp[i-1][0]+dp[i-1][1]

    dp[i][1]=2dp[i-1][0]+2dp[i-1][1]+2dp[i-1][3]

    dp[i][2]=dp[i-1][1]+2dp[i-1][2]

    我们发现n=1e9直接推会T,所以就上矩阵快速幂,初始矩阵为

    | 2 2 0 |

    | 0 0 0 |

    | 0 0 0 |

    转置矩阵为

    | 2 2 0 |

    | 1 2 1 |

    | 0 2 2 |

    代码 

     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<cmath>
     6 #include<cstdio>
     7 #include<cstring>
     8 #include<iostream>
     9 #include<algorithm>
    10 #define RG register int
    11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
    12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
    13 #define ll long long
    14 #define inf (1<<29)
    15 using namespace std;
    16 ll T,n;
    17 const ll mo=10007;
    18 inline int read()
    19 {
    20     int x=0,f=1;char c=getchar();
    21     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    22     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    23     return x*f;
    24 }
    25 
    26 struct Mat{
    27     ll a[3][3];
    28     Mat(){memset(a,0,sizeof(a));}
    29     inline ll * operator [] (const int x){return a[x];}
    30     inline Mat operator *(Mat b)
    31     {
    32         Mat ans;
    33         rep(i,0,2)    rep(j,0,2)    rep(k,0,2)
    34             (ans[i][j]+=(a[i][k]*b[k][j]))%=mo;
    35         return ans;
    36     }
    37 };
    38 
    39 void work()
    40 {
    41     Mat S,T;
    42     S[0][0]=2,S[0][1]=2,S[0][2]=0,
    43     T[0][0]=2,T[0][1]=2,
    44     T[1][0]=1,T[1][1]=2,T[1][2]=1,
    45               T[2][1]=2,T[2][2]=2;
    46     while(n)
    47     {
    48         if(n&1)S=S*T;
    49         T=T*T;
    50         n>>=1;
    51     }
    52     printf("%lld
    ",S[0][0]);
    53 }
    54 
    55 int main()
    56 {
    57     T=read();
    58     while(T--)
    59     {
    60         n=read();
    61         work();
    62     }
    63     return 0;
    64 }
    View Code
  • 相关阅读:
    邻接表
    分治
    当遇到error: stray '241' in program错误的解决方法
    cmd / msys2 添加到右菜单
    洛谷P1003 铺地毯
    【洛谷P3372】【模板】线段树 1
    【codevs1082】线段树练习 3
    【codevs1081】线段树练习 2
    【codevs1080】线段树练习1
    【洛谷P1731】生日蛋糕
  • 原文地址:https://www.cnblogs.com/ibilllee/p/9314593.html
Copyright © 2011-2022 走看看