• CF908G New Year and Original Order(DP,数位 DP)


    又一次降智……

    (数位 DP 原来可以写这么短,学到了)

    问题可以转化为求数位中 $ge k$ 的有恰好 $j$ 位的数的个数。设为 $c_{j,k}$。

    那么答案就是:(考虑把 $k$ 的贡献拆开,比如 $9$ 的贡献拆成 $1$ 的贡献的 $9$ 倍,然后分配到 $1$ 到 $9$)

    $$sum_{1le jle n,1le kle 9}c_{j,k}underbrace{111dots111}_{j}$$

    求 $c_{j,k}$ 可以数位 DP。(此处不是记忆化搜索的形式,所以方程会有点不同)

    $f[i][j][k][l]$ 表示前 $i$ 位,$ge k$ 的有恰好 $j$ 位,$l$ 是有没有顶到上界(就是后面要不要顶着 $n$ 枚举,类似记忆化搜索中的 $limit$)。

    转移较为显然,不再赘述。

    时间复杂度 $O(len^2)$。(有一个 $100$ 的常数)

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=777,mod=1e9+7;
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline int read(){
        int x=0,f=0;char ch=getchar();
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int n,f[maxn][maxn][10][2],ans;
    char s[maxn];
    int calc(int x){
        int pro=1,s=0;
        FOR(i,1,x){
            s=(s+pro)%mod;
            pro=10ll*pro%mod;
        }
        return s;
    }
    int main(){
        scanf("%s",s+1);
        n=strlen(s+1);
        FOR(i,0,9) f[0][0][i][0]=1;
        FOR(i,1,n) FOR(j,0,i) FOR(k,0,9) FOR(l,0,9) if(l<k || j){
            if(l==s[i]-'0') f[i][j][k][0]=(f[i][j][k][0]+f[i-1][j-(l>=k)][k][0])%mod;
            f[i][j][k][1]=(f[i][j][k][1]+f[i-1][j-(l>=k)][k][1])%mod;
            if(l<s[i]-'0') f[i][j][k][1]=(f[i][j][k][1]+f[i-1][j-(l>=k)][k][0])%mod;
        }
        FOR(j,0,n) FOR(k,1,9) ans=(ans+1ll*calc(j)*(f[n][j][k][0]+f[n][j][k][1])%mod)%mod;
        printf("%d
    ",ans);
    }
    View Code
  • 相关阅读:
    MarkDown使用教程
    B+树详解
    B-树(B树)详解
    SQL优化之limit 1
    mysql explain用法和结果的含义
    MySQL 常用内置函数与所有内置函数
    Mac os 相关查找命令
    数据库——自然连接、内连接、外连接(左外连接、右外连接,全连接)、交叉连接
    sql语句执行顺序
    有三个线程,怎么让他们按顺序执行?
  • 原文地址:https://www.cnblogs.com/1000Suns/p/11215836.html
Copyright © 2020-2023  润新知