题目大意:

定义\(R(x) = 每个数在各数位排序后得到的数\)
例如:\(R(321597) = 123579\)
给定一个\(n<=10^{700}\),求\(\sum _{i=1}^n R(i)\)。答案模上\(10^9+7\)。

思路与解法:

难度比较大的一题。显然是要数位\(DP\)的。
最直白的想法就是:求出\(g[i][j]\)表示数字在\(R(x)\)的第\(j\)位出现的次数。
有了这个我们就可以计算答案了。 但是这个玩意不好\(DP\)处理。
考虑数字\(num\)在\(f(x)\)的第\(j\)位出现的条件:\(R(x)\)中大于等于\(num\)的数字有\(j\)个。
这个东西就可以\(DP\)了:
\(f[i][j][k][0/1]\)表示当前确定了\(i\)位数字,
数位中大于等于\(k\)的数位有\(j\)个,数位限制状态为\(0/1\)的数的个数。
转移比较简单,枚举下一位放什么即可。
然后初值不好处理,所以手玩\(i=1\)的,把\(i=1\)当初值就行了。
处理出了\(f[n][j][num][1]\)后,就比较好算答案了。
.
记录后缀和\(ans[num][j] = \sum_{i=j}^n f[n][i][num][1]\)。
那么\(g[i][j] = ans[num][j] - ans[num+1][j]\),就把\(g[i][j]\)求出来了。
然后用\(g[i][j]\)直接计算答案即可。

实现代码:

注:屏幕较窄的电脑上看 代码可能格式不太好,最好拷贝到编辑器后再看。

#include<bits/stdc++.h>
#define RG register
#define IL inline
#define ll long long
#define _ 705
#define mod 1000000007
using namespace std;

ll Ans,ten; int n , num[ _ ];
ll f[ _ ][ _ ][ 10 ][ 2 ],ans[ _ ][ _ ]; char ch[ _ ];

IL void Add(RG ll &x,RG ll y){ x += y; if(x>=mod)x-=mod; }

int main(){
    scanf("%s",ch); n = strlen( ch );
    for(RG int i = 1; i <= n;i ++)
        num[i] = ch[ n-i ] - '0';
    for(RG int t = 0; t <= 9; t ++){
        if(t > num[1])
            f[1][0][t][0] = t , f[1][0][t][1] = num[1]+1 , f[1][1][t][0] = 10-t , f[1][1][t][1] = 0;
        else
            f[1][0][t][0] = t , f[1][0][t][1] = t , f[1][1][t][0] = 10-t , f[1][1][t][1] = num[1]-t+1;
    }
    for(RG int i = 2; i <= n; i ++){
        for(RG int j = 0; j <= i; j ++)
            for(RG int k = 0; k <= 9; k ++){
                for(RG int t = 0; t <= 9; t ++){
                    if(t >= k){
                        Add( f[i][j][k][0] , f[i-1][j-1][k][0] );
                        if( t < num[i] )
                            Add( f[i][j][k][1] , f[i-1][j-1][k][0] );
                        else if( t == num[i] )
                            Add( f[i][j][k][1] , f[i-1][j-1][k][1] );
                    }
                    else if(t < k){
                        Add( f[i][j][k][0] , f[i-1][j][k][0] );
                        if( t < num[i] )
                            Add( f[i][j][k][1] , f[i-1][j][k][0] );
                        else if( t == num[i] )
                            Add( f[i][j][k][1] , f[i-1][j][k][1] );
                    }
                }
            }
        }
    for(RG int nm = 0; nm <= 9; nm ++)
        for (int i = n ; i >= 1 ; i --)
            (f[n][i][nm][1] += f[n][i+1][nm][1]) %= mod , ans[nm][i]=f[n][i][nm][1];
    Ans = 0; ten = 1;
    for(RG int i = 1; i <= n; ten*=10,ten %= mod,i ++)
        for(RG int nm = 1; nm <= 9; nm ++)
            Add( Ans , ( ((ans[nm][i] - ans[nm+1][i]) % mod + mod) % mod * ten % mod * nm % mod) );
    cout << Ans;  return 0;
}

CF908G Original Order的更多相关文章

  1. 【CF908G】New Year and Original Order(动态规划)

    [CF908G]New Year and Original Order(动态规划) 题面 洛谷 CF 题解 设\(f[i][j][k][0/1]\)表示当前填到了第\(i\)位,有\(j\)个大于等于 ...

  2. 【CF908G】New Year and Original Order 数位DP

    [CF908G]New Year and Original Order 题意:令S(i)表示将i中所有数位上的数拿出来,从小到大排序后组成一个新的数的值.如S(50394)=3459.求$\sum\l ...

  3. 【CF908G】New Year and Original Order

    [CF908G]New Year and Original Order 题面 洛谷 题解 设\(f[i][j][k][l]\)表示当前在第\(i\)位有\(j\)位大于等于\(k\),当前有没有卡上界 ...

  4. Good Bye 2017 G. New Year and Original Order

    G. New Year and Original Order time limit per test 2 seconds memory limit per test 256 megabytes inp ...

  5. CF908G New Year and Original Order 数位DP

    传送门 看到数据范围到\(10^{700}\)毫无疑问数位DP.那么我们最重要的问题是如何有效地维护所有数位排序之后的数的值. 对于某一个数\(x\),设\(f_{x,i} (i \in [1,9]) ...

  6. CF908G New Year and Original Order

    题面 题意翻译 给定$n<=10^{700}$,问$1$到$n$中每个数在各数位排序后得到的数的和.答案$mod\;10^9+7$. 题解 考虑设$f[i][j][k][0/1]$表示前$i$位 ...

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

    又一次降智…… (数位 DP 原来可以写这么短,学到了) 问题可以转化为求数位中 $\ge k$ 的有恰好 $j$ 位的数的个数.设为 $c_{j,k}$. 那么答案就是:(考虑把 $k$ 的贡献拆开 ...

  8. 908G New Year and Original Order

    传送门 分析 代码 #include<iostream> #include<cstdio> #include<cstring> #include<string ...

  9. Codeforces908G. New Year and Original Order

    给n<=10^700,问1到n中每个数在各数位排序后得到的数的和.答案膜1e9+7. 一看就是数位DP啦..然而并没有什么思路.. 可以尝试统计n(i,j)表示数j在第i位的出现次数,知道了这个 ...

随机推荐

  1. CSS3及JS媒体查询教程

    CSS3媒体查询: 语法: <media_query_list>:<media_query>[,<media_query>] <media_query> ...

  2. docker-compose快速搭建lnmp+redis服务器环境

    因为我用的是MacOS 安装docker sudo yum update sudo tee /etc/yum.repos.d/docker.repo <<-'EOF' [dockerrep ...

  3. yii2 源码分析Event类分析 (三)

    转载请注明链接:http://www.cnblogs.com/liuwanqiu/p/6739880.html Event是所有事件的基类,它继承Object类 Event类上面的注释的大致意思: * ...

  4. C++ 11 左值,右值,左值引用,右值引用,std::move, std::foward

    这篇文章要介绍的内容和标题一致,关于C++ 11中的这几个特性网上介绍的文章很多,看了一些之后想把几个比较关键的点总结记录一下,文章比较长.给出了很多代码示例,都是编译运行测试过的,希望能用这些帮助理 ...

  5. .net core 2.0学习笔记(二):部署到Windows和Liunx系统

    .Net Core最大的亮点就是跨平台了,下面介绍下在Windows下和Liunx下的部署. 首先发布项目文件,点击网站项目右键 发布: 从下图发布的文件图片可以看出,不像以前bin目录下有很多dll ...

  6. LeetCode第六天

    第六天 30.(219) Contains Duplicate II JAVA class Solution { public boolean containsNearbyDuplicate(int[ ...

  7. nyoj913 取石子(十) SG函数 + Nimm博弈

    思路: 第一堆:SG = n % 3; 第二堆:无规律,打表即可,用hash比set快很多; 第三堆:SG = n; 第四堆:无规律 第五堆:SG = n % 2; 第六堆:SG = n % (i + ...

  8. 【BZOJ1095】 Hide 捉迷藏

    Time Limit: 4000 ms   Memory Limit: 256 MB Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.W ...

  9. SPFA+SLF+LLL优化模板

    #include<algorithm> #include <iostream> #include <cstdlib> #include <cstring> ...

  10. ORACLE关于段的HEADER_BLOCK的一点浅析

    在学习段(segment).区间(extent)时,对段的HEADER_BLOCK有一些疑问,本文记录一下探究的实验过程以及相关总结,,如有不对的地方,敬请指出.以SCOTT.EMP表为例(下面测试环 ...