zoukankan      html  css  js  c++  java
  • 一道记数题

    题面

    笑死,一开始考虑只有一层的情况,推出递推公式之后成功跑偏wwww,然后死也找不出两层情况的递推公式

    最后离考试结束还有30min的时候才猛然发现,淦可以直接按照每一列的情况暴力(其实也不暴力)转移啊。

    设第一列的颜色是(1,2),再设0颜色是其他m-2种颜色的集合体。那么我们就有了(0,0)(0,1)(0,2)(1,0)(1,2)(2,0)(2,1)这七种状态。

    然后我们只需要考虑相邻的两列之间这7种状态的笛卡尔积这7*7种转移的方案数,就可以构造转移矩阵A了

    (0,0,0,0,1,0,0) * A^n这个向量的第5维的值就是所求(因为绕了一圈回来必须回到(1,2)这个状态)。

    最后还需要再把这个乘上  m*(m-1) 枚举1和2具体是哪个颜色,就是答案了。

    tip: 构造A其实才是这个题最难的部分,这里留给聪明的你们来思考

    (然后我在考试结束前的一个if里少写了一个条件WA了,考试结束后10min才改对呜呜呜)

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int ha = 1e9+7;
    
    inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
    inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
    ll n;
    int m;
    
    struct matrix{
        int a[9][9];
    
        matrix(){
            memset(a,0,sizeof(a));
        }
    
        matrix operator * (const matrix &u)const{
            matrix r;memset(r.a,0,sizeof(r.a));
            for(int k=0;k<9;k++)
                for(int i=0;i<9;i++)
                    for(int j=0;j<9;j++) ADD(r.a[i][j],a[i][k] * (ll)u.a[k][j] % ha);
            return r;
        }   
    
        inline void construct(){
            for(int i=0;i<9;i++)
                for(int j=0;j<9;j++){
                    int c = i/3,d = i%3,A = j/3,B = j%3;
                    if((c>0 && A == c) || (d>0 && B==d) || (A == B && A>0)) continue;
                    if(A > 0 && B > 0) a[i][j] = 1;
                    else if((A>0) + (B>0) == 1){
                        if(A>0) a[i][j] = (d>0?max(m-2,0):max(m-3,0));
                        else a[i][j] = (c>0?max(m-2,0):max(m-3,0));
                    }
                    else{
                        if(c>0 && d>0) a[i][j] = max(m-2,0)*(ll)max(m-3,0)%ha;
                        else if(c>0 || d>0) a[i][j] = max(m-3,0)*(ll)max(m-3,0)%ha;
                        else a[i][j] = add(max(m-3,0),max(m-4,0) * (ll)max(0,m-4)%ha);
                    }
                }
        }
    };
    
    int main(){
        cin>>n>>m;
        if(m==1){
            cout<<0<<endl;
            return 0;
        }
        matrix x;
        x.construct();
    
        matrix ans;
        for(int i=0;i<9;i++) ans.a[i][i] = 1;
    
        for(;n;n>>=1,x=x*x) if(n&1) ans = ans * x;
    
        cout<<ans.a[5][5] * (ll)m % ha *(ll)(m-1) %ha<<endl;
        return 0;
    }
    

      

    我爱学习,学习使我快乐
  • 相关阅读:
    多线程
    socket
    十一、内置模块
    十、模块与包
    Javaweb学习笔记11 JDBC
    Javaweb学习笔记10 4种范围对象
    Javaweb学习笔记9 application
    Javaweb学习笔记8 session与cookie区别
    Javaweb学习笔记7 session
    Javaweb学习笔记6 jsp页面元素
  • 原文地址:https://www.cnblogs.com/JYYHH/p/14775369.html
Copyright © 2011-2022 走看看