hdu 2604 Queuing (矩阵乘法 求递推式)

http://acm.hdu.edu.cn/showproblem.php?pid=2604

题意:

有 l 个人  排成一队,这l 个人可以 f(女人),也可能是 m(男人),求 这些人中 不含有 fmf  和 fff 这样的子序列的 个数.

 结果  % mod

 

输入 l, mod;

 

题解:

由于L 比较大 ,我们可以求出 递推式后 用矩阵 乘法 求结果。

 

接下来我们要考虑递推到n时新生成的E-queues,显然只考虑n-1时E-queues的最后两位的情况即可

我们用 an 表示 以 开头为 fm 的数量 ,bn 表示 开头为 ff的数量 ,cn 表示 开头为 mf 的数量 dn 表示 开头为 mm 的数量。

an = d(n-1);

bn = a(n - 1);

cn = a(n - 1) + b(n - 1);

dn = c(n - 1) + d(n - 1);

最后 求 an+bn+cn+dn 即可

 

 an        0 0 0 1           a(n -1)

bn   =   1 0 0 0      *   b(n - 1)

cn        1 0 1 0           c(n - 1)

dn        0 0 1 1          d(n - 1)

 

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include< set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include< string>
 11  #define Min(a,b) a<b?a:b
 12  #define Max(a,b) a>b?a:b
 13  #define CL(a,num) memset(a,num,sizeof(a));
 14  #define eps  1e-12
 15  #define inf 100000000
 16  #define mx 1<<60
 17  #define ll   __int64
 18  const  double pi  = acos(- 1.0);
 19  const  int maxn =  200;
 20  using  namespace std;
 21  struct matrix
 22 {
 23      int m[ 4][ 4];
 24 }p,b,e;
 25  int mod;
 26  void init()
 27 {
 28     CL(p.m, 0);
 29     p.m[ 0][ 3] =  1;
 30     p.m[ 1][ 0] =  1;
 31     p.m[ 2][ 0] =  1;
 32     p.m[ 2][ 1] =  1;
 33     p.m[ 3][ 2] =  1;
 34     p.m[ 3][ 3] =  1;
 35 
 36     CL(b.m, 0);
 37     b.m[ 0][ 0] =  1;
 38     b.m[ 1][ 0] =  1;
 39     b.m[ 2][ 0] =  1;
 40     b.m[ 3][ 0] =  1;
 41 
 42      for( int i =  0 ; i <  4;i++)
 43     {
 44         e.m[i][i] =  1;
 45     }
 46 
 47 }
 48 matrix mtmul(matrix a,matrix b)
 49  {
 50       int i,j,k;
 51      matrix c;
 52      CL(c.m, 0);
 53       for(i = 0 ; i <  4;i++)
 54      {
 55           for(k =  0; k <  4;k++)
 56          {
 57 
 58                   if(a.m[i][k])
 59               for(j =  0 ; j <  4;j++)
 60              {
 61                  c.m[i][j] += a.m[i][k]*b.m[k][j];
 62                  c.m[i][j]%=mod;
 63 
 64              }
 65          }
 66      }
 67       return c;
 68  }
 69  matrix mtpow(matrix d, int k)
 70 {
 71     matrix a;
 72      if(k ==  1return d;
 73      int mid = k /  2;
 74     a = mtpow(d,k/ 2);
 75     a = mtmul(a,a);
 76      if(k &  1)
 77     {
 78         a = mtmul(a,d);
 79     }
 80      return a;
 81 
 82 
 83 }
 84  int main()
 85 {
 86      int len,i;
 87 
 88      while(scanf( " %d%d ",&len,&mod)!=EOF)
 89     {
 90 
 91          init() ;
 92          if(len ==  1)
 93         {
 94             printf( " %d\n ", 2 % mod);
 95 
 96              continue ;
 97         }
 98          if(len ==  2)
 99         {
100             printf( " %d\n ", 4 % mod);
101              continue ;
102         }
103 
104 
105         matrix d ;
106        d = mtpow(p,len -  2);
107 
108 
109         d = mtmul(d,b);
110          int ans =  0;
111          for(i =  0 ; i <  4;i++)
112         {
113             ans += d.m[i][ 0];
114             ans %= mod;
115         }
116         printf( " %d\n ",ans);
117     }
118 }

 

转载于:https://www.cnblogs.com/acSzz/archive/2012/08/30/2664526.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值