[矩阵快速幂专题]

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

Queuing

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8168    Accepted Submission(s): 3581

Problem Description
Queues and Priority Queues are data structures which are known to most computer scientists. The Queue occurs often in our daily life. There are many people lined up at the lunch time. 

  Now we define that ‘f’ is short for female and ‘m’ is short for male. If the queue’s length is L, then there are 2 L numbers of queues. For example, if L = 2, then they are ff, mm, fm, mf . If there exists a subqueue as fmf or fff, we call it O-queue else it is a E-queue.
Your task is to calculate the number of E-queues mod M with length L by writing a program.
 
Input
Input a length L (0 <= L <= 10  6) and M.
 
Output
Output K mod M(1 <= M <= 30) where K is the number of E-queues with length L.
 
Sample Input
3 8 4 7 4 8
 
Sample Output
6 2 1
题意:求一个只含字符f和字符m的长度为L的字符串的种类数%m,要求其子串中不含有fff和fmf。
题解:设f(n)为长度为n的满足条件的字符串的个数,那么考虑第n个字符,第n个字符为m的话满足条件的个数为f(n-1),第n个字符为f的话,则最后几个字符应该为Xmmf或者Xmmff,其中X表示可以为m或者f,则个数也就是f(n-3)和f(n-4),所以f(n)=f(n-1)+f(n-3)+f(n-4),矩阵快速幂即可
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define debug(x) cout<<"["<<#x<<"]"<<"  "<<x<<endl;
 5 ll w[4][4],e[4][4];
 6 const int N=4;
 7 ll tmp[N][N],mod;
 8 void multi(ll a[][N],ll b[][N],int n)
 9 {
10     memset(tmp,0,sizeof tmp);
11     for(int i=0;i<n;i++)
12         for(int j=0;j<n;j++)
13         for(int k=0;k<n;k++)
14         {tmp[i][j]+=a[i][k]%mod*b[k][j]%mod;tmp[i][j]%=mod;}
15     for(int i=0;i<n;i++)
16         for(int j=0;j<n;j++)
17         a[i][j]=tmp[i][j];
18 }
19 ll res[N][N];
20 void Pow(ll a[][N],int n)
21 {
22     memset(res,0,sizeof res);//n是幂,N是矩阵大小
23     for(int i=0;i<N;i++) res[i][i]=1;
24     while(n)
25     {
26         if(n&1)
27             multi(res,a,N);//res=res*a;复制直接在multi里面实现了;
28         multi(a,a,N);//a=a*a
29         n>>=1;
30     }
31 }
32 void init(){
33     w[0][0]=1;
34     w[0][1]=0;
35     w[0][2]=1;
36     w[0][3]=1;
37 
38     w[1][0]=1;
39     w[1][1]=0;
40     w[1][2]=0;
41     w[1][3]=0;
42 
43     w[2][0]=0;
44     w[2][1]=1;
45     w[2][2]=0;
46     w[2][3]=0;
47 
48     w[3][0]=0;
49     w[3][1]=0;
50     w[3][2]=1;
51     w[3][3]=0;
52 }
53 int main()
54 {
55     int l;
56     e[0][0]=9;
57     e[1][0]=6;
58     e[2][0]=4;
59     e[3][0]=2;
60     while(scanf("%d%lld",&l,&mod)==2){
61         init();
62         if(l<4){
63             printf("%lld\n",e[l-1][0]%mod);
64         }
65         else{
66             Pow(w,l-4);
67             multi(res,e,4);
68             printf("%lld\n",res[0][0]);
69         }
70     }
71     return 0;
72 }
View Code

 

转载于:https://www.cnblogs.com/MekakuCityActor/p/10853412.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值