HDU 2604 Queuing

题意:f代表男,m代表女,给定长度L,有2^L个不同组合的字符串(f、m相间),不能出现fmf和fff,问有几种组合。

思路:只要能找到递推公式就可以马上切掉这题。

设f(n)为字符串长度为n时复合条件的字符串个数,以字符串最后一个字符为分界点,当最后一个字符为m时前n-1个字符没有限制,即为f(n-1);当最后一个字符为f时就必须去除最后3个字符是fmf和fff的情况,在考虑最后两个字符为mf和ff的情况,显然不行;最后3个字符为fmf、mmf和fff、mff时只有当最后3个字符为mmf时前n-3个字符没有限制,即为f(n-3),当为mff时第n-3个字符可能为f因而对前n-3个字符串有限制;最后4个字符为fmff和mmff时mmff可行。这样就讨论完了字符串的构成情况,得出结论:
f(n)=f(n-1)+f(n-3)+f(n-4)
然后就像fibonacci那样构建矩阵用快速幂取模。。。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2604

 

View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <string>
 5 #include <algorithm>
 6 #include <iostream>
 7 using namespace std;
 8 
 9 int f[5]={0,2,4,6,9};
10 typedef struct In{
11     int m[5][5];
12 }Matrix;
13 Matrix init,unit,F;
14 int n,m;
15 
16 void Init(){
17     for(int i=1;i<=4;i++){
18         for(int j=1;j<=4;j++){
19             if(i==1&&j==1) init.m[i][j]=1;
20             else if(i==1&&j==3) init.m[i][j]=1;
21             else if(i==1&&j==4) init.m[i][j]=1;
22             else if(i==2&&j==1) init.m[i][j]=1;
23             else if(i==3&&j==2) init.m[i][j]=1;
24             else if(i==4&&j==3) init.m[i][j]=1;
25             else init.m[i][j]=0;
26             unit.m[i][j]=(i==j);
27             F.m[i][j]=0;
28         }
29     }
30     F.m[1][1]=f[4];
31     F.m[2][1]=f[3];
32     F.m[3][1]=f[2];
33     F.m[4][1]=f[1];
34 }
35 
36 Matrix Mul(Matrix a,Matrix b){
37     Matrix c;
38     for(int i=1;i<=4;i++)
39         for(int j=1;j<=4;j++){
40             c.m[i][j]=0;
41             for(int k=1;k<=4;k++){
42                 c.m[i][j]+=a.m[i][k]*b.m[k][j]%m;
43                 c.m[i][j]%=m;
44             }
45         }
46     return c;
47 }
48 
49 Matrix Pow(Matrix a,Matrix b){
50     while(n){
51         if(n&1) b=Mul(a,b);
52         a=Mul(a,a);
53         n>>=1;
54     }
55     return b;
56 }
57 
58 int main(){
59     
60 //    freopen("data.in","r",stdin);
61 //    freopen("data.out","w",stdout);
62     
63     while(scanf("%d%d",&n,&m)!=EOF){
64         if(n<5){
65             printf("%d\n",f[n]%m);
66             continue;
67         }
68         Init();
69         n-=4;
70         Matrix x=Pow(init,unit);
71         x=Mul(x,F);
72         printf("%d\n",x.m[1][1]%m);
73     }
74     return 0;
75 }

转载于:https://www.cnblogs.com/Hug-Sea/articles/2489222.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值