zoukankan      html  css  js  c++  java
  • Codeforces908G. New Year and Original Order

    给n<=10^700,问1到n中每个数在各数位排序后得到的数的和。答案膜1e9+7。

    一看就是数位DP啦。。然而并没有什么思路。。

    可以尝试统计n(i,j)表示数j在第i位的出现次数,知道了这个数组后就可以算答案了。可以枚举j,做一次DP,f(a,b,0/1)--考虑第a~n个数,有b个j,是否大于给定数字(因为当前大于给定数字不一定dp到前面的数就大于,所以当前大于给定数字的数也是有贡献的),等等光知道有多少j并不能确定第i位是否有j,行不通。

    套路--k(i,j)表示第i位出现的>=j的数字的出现次数,则$n(i,j)=k(i,j)-k(i,j+1)$。现在f(a,b,0/1)中的b则表示有b个>=j的数,那么就可以递推了。用$X_a$表示给定数字第a位是谁:

    1、$j>X_a$:$f(a,b,0)=(f(a+1,b,0)+f(a+1,b,1))*X_a+f(a+1,b,0),f(a,b,1)=(f(a+1,b-1,0)+f(a+1,b-1,1))*(10-j)+(f(a+1,b,0)+f(a+1,b,1))*(j-X_a-1)+f(a+1,b,1)$

    2、$j<=X_a$:$f(a,b,0)=(f(a+1,b,0)+f(a+1,b,1))*j+(f(a+1,b-1,0)+f(a+1,b-1,1))*(X_a-j)+f(a+1,b-1,0),f(a,b,1)=(f(a+1,b-1,0)+f(a+1,b-1,1))*(10-X_a-1)+f(a+1,b-1,1)$。

    还没完,边界条件:1、$j>X_n$:$f(n,0,0)=X_a+1,f(n,0,1)=j-X_a-1,f(n,1,1)=10-j,f(n,1,0)=0$。

    2、$j<=X_n$:$f(n,0,0)=j,f(n,0,1)=0,f(n,1,0)=X_n-j+1,f(n,1,1)=10-X_n-1$。

    这些加一减一、取等取不等的特别注意。把<和=归在一类是之前在草稿纸上推过发现可以合的。

    然后就没了。注意检查膜。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<map>
     6 //#include<bitset>
     7 #include<algorithm>
     8 //#include<cmath>
     9 using namespace std;
    10 
    11 int n;
    12 #define maxn 711
    13 char s[maxn];
    14 const int mod=1e9+7;
    15 int kk[maxn][12],f[maxn][maxn][2];
    16 int main()
    17 {
    18     scanf("%s",s+1); n=strlen(s+1);
    19     for (int j=0;j<=9;j++)
    20     {
    21         int num=s[n]-'0';
    22         if (j>num) {f[n][0][0]=num+1; f[n][1][0]=0; f[n][0][1]=j-num-1; f[n][1][1]=10-j;}
    23         else {f[n][0][0]=j; f[n][1][0]=num-j+1; f[n][0][1]=0; f[n][1][1]=10-num-1;}
    24         
    25         for (int a=n-1;a;a--)
    26         {
    27             int num=s[a]-'0';
    28             if (j>num)
    29             {
    30                 f[a][0][0]=(1ll*(f[a+1][0][0]+f[a+1][0][1])*num+f[a+1][0][0])%mod;
    31                 f[a][0][1]=(1ll*(f[a+1][0][0]+f[a+1][0][1])*(j-num-1)+f[a+1][0][1])%mod;
    32                 for (int b=1,to=n-a+1;b<=to;b++)
    33                 {
    34                     f[a][b][0]=(1ll*(f[a+1][b][0]+f[a+1][b][1])*num+f[a+1][b][0])%mod;
    35                     f[a][b][1]=(1ll*(f[a+1][b-1][0]+f[a+1][b-1][1])*(10-j)
    36                     +1ll*(f[a+1][b][0]+f[a+1][b][1])*(j-num-1)+f[a+1][b][1])%mod;
    37                 }
    38             }
    39             else
    40             {
    41                 f[a][0][0]=(1ll*(f[a+1][0][0]+f[a+1][0][1])*j)%mod;
    42                 f[a][0][1]=0;
    43                 for (int b=1,to=n-a+1;b<=to;b++)
    44                 {
    45                     f[a][b][0]=(1ll*(f[a+1][b][0]+f[a+1][b][1])*j
    46                     +1ll*(f[a+1][b-1][0]+f[a+1][b-1][1])*(num-j)+f[a+1][b-1][0])%mod;
    47                     f[a][b][1]=(1ll*(f[a+1][b-1][0]+f[a+1][b-1][1])*(10-num-1)+f[a+1][b-1][1])%mod;
    48                 }
    49             }
    50         }
    51         for (int i=n;i;i--) f[1][i][0]+=f[1][i+1][0],f[1][i][0]-=f[1][i][0]>=mod?mod:0,kk[i][j]=f[1][i][0];
    52     }
    53     int ans=0;
    54     for (int i=1,ten=1;i<=n;i++)
    55     {
    56         for (int j=0;j<=9;j++)
    57             ans+=1ll*(kk[i][j]-kk[i][j+1]+mod)*ten%mod*j%mod,
    58             ans-=ans>=mod?mod:0,ans+=ans<0?mod:0;
    59         ten=1ll*ten*10%mod;
    60     }
    61     printf("%d
    ",ans);
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    C# 对 TCP 客户端的状态封装
    一个页面从输入url到页面加载完成究竟经历了些什么
    使用mvp+rxjava+retrofit加载数据
    使用mvp+rxjava+retrofit加载数据
    使用mvp+rxjava+retrofit加载数据
    使用mvp+rxjava+retrofit加载数据
    SqlServer性能检测和优化工具使用详细
    SqlServer性能检测和优化工具使用详细
    SqlServer性能检测和优化工具使用详细
    SqlServer性能检测和优化工具使用详细
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8213650.html
Copyright © 2011-2022 走看看