• [UOJ UR#16]破坏发射台


    来自FallDream的博客,未经允许,请勿转载,谢谢。


    传送门

    先考虑n是奇数的情况,很容易想到一个dp,f[i][0/1]表示转移到第i个数,第i个数是不是第一个数的方案数,然后用矩阵乘法优化一下就好了。

    然后考虑n是偶数的情况,发现可以把圈分成两个半圆,dp就多了几维,需要表示两个数分别是是第一个数/第二个数/都不是的方案数。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define MN 10
    #define mod 998244353
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    struct Matrix
    {
        int s[MN+1][MN+1];    
        Matrix(){memset(s,0,sizeof(s));}
        Matrix operator * (const Matrix&b)
        {
            Matrix c;    
            for(int i=0;i<=MN;++i)
                for(int j=0;j<=MN;++j)
                    for(int k=0;k<=MN;++k)
                        c.s[i][j]=(c.s[i][j]+1LL*s[i][k]*b.s[k][j])%mod;
            return c;
        }
    }A,B;
    int n,m;
    
    int Calc(int x,int y)
    {
        if(!x)
        {
            if(!y) return m-3;    
            else return 1;
        }
        if(x==1)
        {
            if(y==0) return m-2;
            else if(y==2) return 1;
            else return 0;     
        }
        if(x==2)
        {
            if(y==0) return m-2;    
            else if(y==1) return 1;
            else return 0;        
        }
    }
    
    int main()
    {
        n=read();m=read();
        if(m==1) return 0*printf("%d
    ",n==1);
        if(n&1)
        {
            B.s[1][0]=1;
            A.s[1][0]=1;
            A.s[0][0]=m-2;
            A.s[0][1]=m-1;
            for(--n;n;n>>=1,A=A*A) if(n&1) B=A*B;
            printf("%d
    ",1LL*B.s[0][0]*m%mod);
        }
        else
        {
            if(n==4&&m==2) return 0*puts("0");
            if(m==2) return 0*puts("2");B.s[5][0]=1;
            for(int i=0;i<3;++i)
                for(int j=0;j<3;++j) if(i!=j||i==0) 
                    for(int k=0;k<3;++k)    
                        for(int l=0;l<3;++l) if(k!=l||k==0)    
                        {
                            A.s[k*3+l][i*3+j]=1LL*Calc(i,k)*Calc(j,l)%mod;
                            if(k==0&&l==0) 
                            {
                                if(1LL*(m-2)*(m-2)+m-2-(i==0)-(j==0)<0) A.s[k*3+l][i*3+j]=0;
                                else (A.s[k*3+l][i*3+j]+=mod-(m-2-(i==0)-(j==0)))%=mod;
                            }
                        }
            int ans=0;
            for(n>>=1,--n;n;n>>=1,A=A*A) if(n&1) B=A*B;
            for(int i=0;i<9;++i) 
            {
                int j=i%3,k=i/3;
                if(j==1||k==2) continue;
                ans=(ans+B.s[i][0])%mod;
            }
            printf("%d
    ",1LL*ans*m%mod*(m-1)%mod);
        }
        return 0;
    }
  • 相关阅读:
    均值回归理论,均值回归法则是指万物最终都将回归于其长期的均值
    文本框仅允许输入大于0的正整数
    Angularjs接收服务端的布尔值
    Ajax POST单个对象或多个对象至API
    ASP.NET MVC程序重构
    查询数据库创建时间
    查询MS SQL的版本号
    获取Data和Log默认路径
    快速查找对象
    表关联使用INNER JOIN实现更新功能
  • 原文地址:https://www.cnblogs.com/FallDream/p/uoj241.html
Copyright © 2020-2023  润新知