202006-4 CCF CSP认证 1246(digits) 96分 动态规划

这个代码并不能通过那个第25号花里胡哨样例,主要针对的是 |s| <= 2的数据。

   主要呢我们发现啊,查询的数据可能是啥呢,首先我们考虑1位的(|s| == 1)的

   那无非就 1,2,4,6 呗,这简单啊,明显可以dp解决,dp [n] [1-4]   第二维  1-4 分别代表4个数字

  •    1 可以产生  2       
  •    2  可以产生 4
  •    3  可以产生  1 和 6
  •    4  可以产生  6 和 4

    睿智的读者已经心里写出来转移方程,提交,32分,这不行啊~~。

    等等,两位的情况似乎也就那么几种啊。

    16,26,41,44,46,61,62,64,66,42

    于是我们先编个号哈。

id 1 2 3 4 5 6 7 8 9 10 11 12 13 14

val

1 2 4 6 16 26 41 44 46 61 62 64 66 42

(为啥42在最后一号呢,因为42在题目给的图片中没有出现,会在第10次迭代中出现,读者想怎么编号都可以,对应的写dp方程即可)

  怎么转移呢,可以发现啊

扫描二维码关注公众号,回复: 11535589 查看本文章
  • 1可以产生2
  • 2可以产生4
  • 4可以产生1,6,16 
  • 6可以产生6,4,64
  • 16可以产生 264  (我们这里只计算标红了的26,读者应该懂我意思,我们只计算相邻的影响)
  • 26可以产生 464     也就是dp[ i ] [ 9 ] += dp[ i-1 ][ 6 ];   根据上边的表,9号的46可以由6号产生嘛
  • 41可以产生 162    
  •    。。。后边我就懒得写了

       于是我们可以写出一个超长的dp ,  我在下边的代码中注释掉的那群 (可能要说博主沙比的那群乱七八糟的)dp 就是这个做法,提交,发现64 ,啧啧啧,这也不行啊。发现数据到了1e9,那就矩阵快速幂优化一下呗。

       这个矩阵对于大家来说也太简单了吧,代码中那个根据注释掉的dp公式写出来的。

提交一看,96,啧啧啧,挺满足了,最后一个样例咱也不知道要考啥。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1e5+5;
ll dp[500005][16];
const int mod = 998244353;
struct matrix{
    ll mat[16][16];
}res,ans;

matrix mat_mul(matrix a,matrix b)
{
    matrix tmp={0};
    for(int i=1;i<=14;i++)
        for(int j=1;j<=14;j++)
            for(int k=1;k<=14;k++)
                tmp.mat[i][j] = (tmp.mat[i][j]%mod+((a.mat[i][k]%mod)*(b.mat[k][j]%mod))%mod)%mod;
    return tmp;
}

void qpow(int t)
{
    for(int i=1;i<=14;i++)
        for(int j=1;j<=14;j++)
        {
            if(i==j)
                ans.mat[i][j] = 1;
            else
                ans.mat[i][j] = 0;
        }

    while(t)
    {
        if(t&1)
        {
            ans = mat_mul(ans,res);
        }
        res = mat_mul(res,res);
        t>>=1;
    }
}
int ini[15];
map<string,int>mp;
void init()
{
    ini[1] = 1;
    int a[16][16] ={
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},  //0
        {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},  //1
        {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},  //2
        {0,0,1,0,1,0,0,0,0,0,0,0,0,0,0},  //3
        {0,0,0,1,1,0,0,0,0,0,0,0,0,0,0},  //4
        {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},  //5
        {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0},  //6
        {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0},  //7
        {0,0,0,0,0,0,0,0,0,0,0,1,0,0,0},  //8
        {0,0,0,0,0,0,1,0,0,0,0,0,0,1,0},  //9
        {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0},  //10
        {0,0,0,0,0,0,0,1,0,0,0,0,0,0,0},  //11
        {0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},  //12
        {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0},  //13
        {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0}   //14
    };
    for(int i=1;i<=14;i++){
        for(int j=1;j<=14;j++){
            res.mat[i][j] = a[i][j];
        }
    }

    mp["1"] = 1; mp["2"] = 2; mp["4"] = 3; mp["6"] = 4;
    mp["16"] = 5; mp["26"] = 6; mp["41"] = 7; mp["44"] = 8;
    mp["46"] = 9; mp["61"] = 10; mp["62"] = 11; mp["64"] = 12;
    mp["66"] = 13; mp["42"] = 14;
}
int main()
{
    init();
    int n;
    cin>>n;
    qpow(n);
//    dp[0][1] = 1;
//    for(int i=1;i<=n;i++){
//        dp[i][1] += dp[i-1][3];
//        dp[i][2] += dp[i-1][1];
//        dp[i][3] += dp[i-1][2] + dp[i-1][4];
//        dp[i][4] += dp[i-1][3] + dp[i-1][4];
//        dp[i][5] += dp[i-1][3];
//        dp[i][6] += dp[i-1][5];
//        dp[i][7] += dp[i-1][12];
//        dp[i][8] += dp[i-1][11];
//        dp[i][9] += dp[i-1][6] + dp[i-1][13];
//        dp[i][10] += dp[i-1][8];
//        dp[i][11] += dp[i-1][7];
//        dp[i][12] += dp[i-1][4] + dp[i-1][14];
//        dp[i][13] += dp[i-1][9];
//        dp[i][14] += dp[i-1][10];
//        for(int j=1;j<=14;j++){
//            dp[i][j] %= mod;
//        }
//    }
    string s;
    cin>>s;
    int idx = mp[s];
    ll anss = 0;
    for(int i=1;i<=14;i++){
        anss = (anss +  (ans.mat[idx][i] * ini[i]%mod) )%mod;
    }
    cout<<anss<<endl;
    //cout<<dp[n][idx]<<endl;;
}

猜你喜欢

转载自blog.csdn.net/qq_41645482/article/details/107848383