给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$。

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

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

 //#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<map>
//#include<bitset>
#include<algorithm>
//#include<cmath>
using namespace std; int n;
#define maxn 711
char s[maxn];
const int mod=1e9+;
int kk[maxn][],f[maxn][maxn][];
int main()
{
scanf("%s",s+); n=strlen(s+);
for (int j=;j<=;j++)
{
int num=s[n]-'';
if (j>num) {f[n][][]=num+; f[n][][]=; f[n][][]=j-num-; f[n][][]=-j;}
else {f[n][][]=j; f[n][][]=num-j+; f[n][][]=; f[n][][]=-num-;} for (int a=n-;a;a--)
{
int num=s[a]-'';
if (j>num)
{
f[a][][]=(1ll*(f[a+][][]+f[a+][][])*num+f[a+][][])%mod;
f[a][][]=(1ll*(f[a+][][]+f[a+][][])*(j-num-)+f[a+][][])%mod;
for (int b=,to=n-a+;b<=to;b++)
{
f[a][b][]=(1ll*(f[a+][b][]+f[a+][b][])*num+f[a+][b][])%mod;
f[a][b][]=(1ll*(f[a+][b-][]+f[a+][b-][])*(-j)
+1ll*(f[a+][b][]+f[a+][b][])*(j-num-)+f[a+][b][])%mod;
}
}
else
{
f[a][][]=(1ll*(f[a+][][]+f[a+][][])*j)%mod;
f[a][][]=;
for (int b=,to=n-a+;b<=to;b++)
{
f[a][b][]=(1ll*(f[a+][b][]+f[a+][b][])*j
+1ll*(f[a+][b-][]+f[a+][b-][])*(num-j)+f[a+][b-][])%mod;
f[a][b][]=(1ll*(f[a+][b-][]+f[a+][b-][])*(-num-)+f[a+][b-][])%mod;
}
}
}
for (int i=n;i;i--) f[][i][]+=f[][i+][],f[][i][]-=f[][i][]>=mod?mod:,kk[i][j]=f[][i][];
}
int ans=;
for (int i=,ten=;i<=n;i++)
{
for (int j=;j<=;j++)
ans+=1ll*(kk[i][j]-kk[i][j+]+mod)*ten%mod*j%mod,
ans-=ans>=mod?mod:,ans+=ans<?mod:;
ten=1ll*ten*%mod;
}
printf("%d\n",ans);
return ;
}

最新文章

  1. nth-of-type
  2. 主成分分析PCA的前世今生
  3. git工作流程
  4. HTML 中按钮作为form表单元素提交特性两则 --- 参HTML考标准分析
  5. linux库之pam
  6. HDU5008 Boring String Problem(后缀数组)
  7. JS代码片段:日期格式化
  8. nginx安装-源码编译
  9. Android FastJson解析
  10. [置顶] 浅谈Android的资源编译过程
  11. 以往CSDN博文目录
  12. 《java.util.concurrent 包源码阅读》20 DelayQueue
  13. vsCode打开多个终端
  14. Open CDN 2.0管控端和节点端安装
  15. idea 设置光标回到上一次位置的快捷键
  16. 完全使用UDP登录Linux
  17. pyaudio
  18. poj1562 Oil Deposits 深搜模板题
  19. [原][osgEarth][JSBSim]重新整理使用JSBSim飞机动力模拟的使用
  20. hadoop遇到的问题及处理

热门文章

  1. 转】Mahout构建图书推荐系统
  2. WebForm 开发方式,简单使用
  3. WPF学习09:数据绑定之 Binding to List Data
  4. 手写一套迷你版HTTP服务器
  5. TCP/UDP套接字 java socket编程实例
  6. 【C++】模板简述(二):函数模板
  7. Sql Server 2012 事务复制遇到的问题及解决方式
  8. php与其他一些相关工具的安装步骤分享
  9. 6-Java-C(移动距离)
  10. 类unix系统 递归删除指定文件