zoukankan      html  css  js  c++  java
  • [HAOI2015]数字串拆分

    题目描述

    你有一个长度为n的数字串。定义f(S)为将S拆分成若干个1~m的数的和的方案数,比如m=2时,f(4)=5,分别为4=1+1+1+1你可以将这个数字串分割成若干个数字(允许前导0),将他们加起来,求f,并求和。比如g(123)=f(1+2+3)+f(1+23)+f(12+3)+f(123)。已知字符串和m后求答案对998244353(7*17*223+1,一个质数)取模后的值。

    输入输出格式

    输入格式:

    第一行输入一个字符串,第二行输入m

    输出格式:

    仅输出一个数表示答案

    输入输出样例

    输入样例#1: 复制
    123
    3
    输出样例#1: 复制
    394608467

    说明

    对于100%的数据,字符串长度不超过500,m<=5

    先求出$f[s]$

    显然$f[i]=sum_{j=i-m}^{i-1}f[j]$

    如果i特别大就可以用一个m*m的转移矩阵

    也就是$(f_{i-m+1},f_{i-m+2},...f_{i})$的转移矩阵

    预处理出A[i][j]表示数S为j*10^i的转移矩阵

    对于$g$的转移:

    显然$g[i]=sum_{j=0}^{i-1}g[j]*D[j+1][i]$

    $D[j+1][i]$表示j+1~i位构成的数的转移矩阵,显然可以通过A推出

    g也要用一个矩阵表示

    g[0]初始矩阵使$g_0=1$,也就是$(0,0,..,0,1)$

    最后输出矩阵中代表$g_n$的方案,位置是(1,m)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 int Mod=998244353;
     8 struct Matrix
     9 {
    10     int a[6][6];
    11 }f[501],A[501][10],now;
    12 char s[502];
    13 int n,m,ans;
    14 Matrix operator *(const Matrix &a,const Matrix &b)
    15 {
    16     int i,j,l;
    17     Matrix res;
    18     memset(res.a,0,sizeof(res.a));
    19     for (i=1; i<=m; i++)
    20     {
    21         for (j=1; j<=m; j++)
    22         {
    23             for (l=1; l<=m; l++)
    24             {
    25                 res.a[i][j]+=1ll*a.a[i][l]*b.a[l][j]%Mod;
    26             if (res.a[i][j]>=Mod)
    27             res.a[i][j]-=Mod;
    28             }
    29         }
    30     }
    31     return res;
    32 }
    33 Matrix operator +(const Matrix &a,const Matrix &b)
    34 {
    35     int i,j,l;
    36     Matrix res;
    37     memset(res.a,0,sizeof(res.a));
    38     for (i=1; i<=m; i++)
    39     {
    40         for (j=1; j<=m; j++)
    41         {
    42         res.a[i][j]=(a.a[i][j]+b.a[i][j])%Mod;
    43         }
    44     }
    45     return res;
    46 }
    47 int main()
    48 {int i,j;
    49   cin>>s+1;
    50   n=strlen(s+1);
    51   cin>>m;
    52   for (i=1;i<=m;i++)
    53     {
    54       A[0][0].a[i][i]=1;
    55     }
    56   for (i=1;i<=m;i++)
    57     {
    58       A[0][1].a[i][m]=1;
    59     }
    60   for (i=1;i<m;i++)
    61     {
    62       A[0][1].a[i+1][i]=1;
    63     }
    64   for (i=2;i<=9;i++)
    65     {
    66       A[0][i]=A[0][i-1]*A[0][1];
    67     }
    68   for (i=1;i<=n;i++)
    69     {
    70       A[i][0]=A[0][0];
    71       A[i][1]=A[i-1][9]*A[i-1][1];
    72       for (j=2;j<=9;j++)
    73       {
    74         A[i][j]=A[i][j-1]*A[i][1];
    75       }
    76     }
    77   f[0].a[1][m]=1;
    78   for (i=1;i<=n;i++)
    79     {
    80       now=A[0][s[i]-'0'];
    81       for (j=i-1;j>=0;j--)
    82       {
    83         f[i]=f[i]+(f[j]*now);
    84         if (j) now=A[i-j][s[j]-'0']*now;
    85       }
    86     }
    87   ans=f[n].a[1][m];
    88   cout<<ans;
    89 }
  • 相关阅读:
    在Android Studio中用Gradle添加Robolectric
    Windows环境下利用github快速配置git环境
    上传Android代码到Jcenter(解决了字符映射的问题)
    RecyclerView和ScrollView嵌套使用
    Android Java类编写规范+优化建议
    3.0之后在LinearLayout里增加分割线
    【转】Android Studio中通过快捷键来提取提取方法
    为什么Android应该根据屏幕分辨率来加载不同的图片文件
    JSON/XML格式化插件比较
    利用在线工具根据JSon数据自动生成对应的Java实体类
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8657880.html
Copyright © 2011-2022 走看看