列表

详情


NC19993. [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

输出:

394608467

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 908ms, 内存消耗: 34144K, 提交时间: 2019-08-21 21:06:35

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int MAXN=505,MODE=998244353;
int m;

inline int add(int x,int y)
{
    return (x+=y)>=MODE?x-MODE:x;
}

struct Mat
{
    int lin, col,**a;
    Mat(int l = 0, int c = 0) : lin(l), col(c)
    {
        a = new int*[lin];
        for(int i = 0; i < lin; ++i) a[i] = new int[col]();
    }
    Mat(const Mat& x) // 拷贝构造函数
    {
        lin = x.lin, col = x.col;
        a = new int*[lin];
        for(int i = 0, j; i < lin; ++i)
            for(a[i] = new int[col], j = 0; j < col; ++j)
                a[i][j] = x[i][j];
    }
    ~Mat() // 析构函数
    {
        for(int i = 0; i < lin; ++i) delete[] a[i];
        delete[] a;
    }
    const int* operator[](int x) const { return a[x]; }
    int* operator[](int x) { return a[x]; }
    Mat& operator=(Mat x)
    {
        swap(a, x.a), swap(lin, x.lin), swap(col, x.col);
        return *this;
    }
    Mat operator*(const Mat& x) const // 带模矩阵乘法
    { // assert(col==x.lin);
        Mat ans(lin, x.col);
        for(int i = 0; i < lin; ++i)
            for(int j = 0; j < x.col; ++j)
                for(int k = 0; k < col; ++k)
                    ans[i][j] = add(ans[i][j], a[i][k] * (ll)x[k][j] % MODE);
        return ans;
    }
    Mat& operator*=(const Mat& x) { return *this = *this * x; }
    Mat& operator+=(const Mat& x)
    { // assert(lin==x.lin&&col==x.col);
        for(int i=0;i<lin;++i)
            for(int j=0;j<col;++j)
                a[i][j]=add(a[i][j],x[i][j]);
        return *this;
    }
    Mat operator^(ll ind) const // 快速幂
    { // assert(lin==col);
        Mat ans(lin, col), base(*this);
        for(int i = 0; i < lin; ++i) ans[i][i] = 1; // 单位阵
        for(; ind; base *= base, ind >>= 1)
            if(ind & 1) ans *= base;
        return ans;
    }
    void print() const
    {
        for(int i=0;i<lin||puts("");++i,puts(""))
            for(int j=0;j<col;++j) printf("%d ",a[i][j]);
    }
};

Mat dp[MAXN][MAXN],multi[10],ans[MAXN];
char str[MAXN];

int main()
{
    int m,L;
    scanf("%s %d",str,&m);
    L=strlen(str);
    Mat A(m,m);
    for(int i=0;i<m-1;++i) A[0][i]=A[i+1][i]=1;
    A[0][m-1]=1;
    multi[0]=A^0;
    for(int i=1;i<10;++i) multi[i]=multi[i-1]*A;
    for(int i=0;i<L;++i) dp[i][i]=multi[(int)str[i]-'0'];
    for(int i=0;i<L-1;++i)
        for(int j=i+1;j<L;++j)
            dp[i][j]=(dp[i][j-1]^10)*dp[j][j];
    for(int i=0;i<L;++i)
    {
        ans[i]=dp[0][i];
        for(int j=0;j<i;++j)
        {
            ans[i]+=ans[j]*dp[j+1][i];
        }
    }
    int sum=ans[L-1][0][0];
    printf("%d\n",sum);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 127ms, 内存消耗: 1128K, 提交时间: 2019-03-09 20:11:52

#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
const int N=1005,Mod=998244353;
int n,m,ch[N];
char st[N];
struct matrix{
    int A[6][6];
}f[15][N],g[N],tran;
matrix operator *(matrix a,matrix b){
    matrix res;
    memset(res.A,0,sizeof(res.A));
    for(int i=1;i<=m;i++)
        for(int k=1;k<=m;k++)
            if(a.A[i][k])
                for(int j=1;j<=m;j++){
                    res.A[i][j]=(res.A[i][j]+(ll)a.A[i][k]*b.A[k][j]%Mod);
                    if(res.A[i][j]>=Mod)res.A[i][j]-=Mod;
                }
    return res;
}
matrix operator +(matrix a,matrix b){
    for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++){
            a.A[i][j]+=b.A[i][j];
            if(a.A[i][j]>=Mod)a.A[i][j]-=Mod;
        }
    return a;
}
matrix fast_pow(matrix x,int e){
    matrix res=x;
    while(e){
        if(e&1)res=res*x;
        x=x*x;
        e>>=1;
    }
    return res;
}
int main(){
    scanf("%s",st+1);
    n=strlen(st+1);
    scanf("%d",&m);
    for(int i=1;i<=n;i++)ch[i]=st[i]-'0';
    for(int i=1;i<=m;i++){
        tran.A[i][m]=f[0][1].A[i][i]=1;
        if(i>1)tran.A[i][i-1]=1;
    }
    for(int i=1;i<=9;i++){
        f[i][1]=f[i-1][1]*tran;
        for(int j=2;j<=n;j++)
            f[i][j]=fast_pow(f[i][j-1],9);
    }
    g[0].A[1][m]=1;matrix tmp;
    for(int i=1;i<=n;i++){
        tmp=f[ch[i]][1];
        for(int j=i-1;j>=0;j--){
            g[i]=g[i]+g[j]*tmp;
            if (j && ch[j])tmp=tmp*f[ch[j]][i-j+1];
        }
    }
    printf("%d\n",g[n].A[1][m]);
    return 0;
}

上一题