zoukankan      html  css  js  c++  java
  • HDU_2604 矩阵快速幂 较难推的公式

    一个排队问题,f代表女,m代表男,f和m出现的几率相等。问一个长为L的队伍不能出现 fmf 和 fff这样的串总共有多少种。

    这个题目的公式递推略难啊。。。我看了别人博客才想明白原来是这么递推出来的。

    首先把前几项写出来。

    L=0 ,ans=0;

    L=1,ans=2;

    L=2,ans=4;

    L=3,ans=6;

    L=4,ans=9;

    规律有点难找,直接递推出来,假设 长度为n的串,n>4,ans[n] 无非就是在 ans[n-1]的基础上加一个 f或者m,如果在ans[n-1]的基础上在队列最后加一个m,则绝对合法,因为不论前面n-1个是怎么排列,最后加一个m,绝对不会构成fmf或者fff,所以 ans[n]+=f[n-1]; 但是如果最后一位加的是f,

    就要分类讨论了:

    这个时候,如果n-1位为m,则 n-2位一定要是m 也就是说 一定要 ans[n-3]+mmf才满足条件,于是ans[n]+=ans[n-3]

    这个时候,如果n-1位为f,则n-2位必定为m(否则就后三位fff了),不仅如此,第n-3位一定要是m(否则就fmf了),所以就要 ans[n-4]+mmff,所以ans+=ans[n-4];

    所以最后的递推出来的公式就是 ans[n]=ans[n-1]+ans[n-3]+ans[n-4];

    得此公式,构造出矩阵。。。凡是学过矩阵快速幂的应该都会写了。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int l,m;
    int date[6];
    struct Mat{
        int mat[5][5];
    };
    Mat s,E;
    Mat operator *(Mat a,Mat b)
    {
        Mat c;
        memset(c.mat,0,sizeof (Mat));
        int i,j,k;
        for (i=0;i<4;i++)
            for (j=0;j<4;j++)
            for (k=0;k<4;k++)
        {
            if(a.mat[i][k] && b.mat[k][j])
                c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
            c.mat[i][j]%=m;
        }
        return c;
    }
    Mat operator ^(Mat a,int x)
    {
        Mat c=E;
        for (;x;x>>=1)
        {
            if (x&1)
                c=c*a;
            a=a*a;
        }
        return c;
    }
    void init()
    {
        date[0]=0;
        date[1]=2;
        date[2]=4;
        date[3]=6;
        date[4]=9;
        memset(s.mat,0,sizeof (Mat));
        memset(E.mat,0,sizeof (Mat));
        s.mat[0][0]=s.mat[0][2]=s.mat[0][3]=1;
        s.mat[1][0]=1;
        s.mat[2][1]=1;
        s.mat[3][2]=1;
    
        for (int i=0;i<4;i++)
            E.mat[i][i]=1;
    }
    int main()
    {
        init();
        while (scanf("%d%d",&l,&m)!=EOF)
        {
            if (l<=4)
            {
                printf("%d
    ",date[l]%m);
                continue;
            }
            Mat ans;
            ans=s^(l-4);
            int sum=0;
            for (int i=0;i<4;i++)
            {
                sum+=ans.mat[0][i]*date[4-i];
            }
            sum%=m;
            printf("%d
    ",sum);
        }
        return 0;
    }
  • 相关阅读:
    百分点零售行业大数据解决方案
    百分点用户标签管理系统
    百分点个性化系统解决方案
    百分点数据洞察系统解决方案
    来学学数据分析吧(二)第一章 预测和关联数量特征
    来学学数据分析吧(一)
    生产者和消费者问题学习以及Java实现
    java中的双重锁定检查(Double Check Lock)
    python学习(十四)面向对象
    python学习(十二)模块
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3445738.html
Copyright © 2011-2022 走看看