当前位置 博文首页 > 文章内容

    CF908G New Year and Original Order

    作者: 栏目:未分类 时间:2020-10-22 18:00:45

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    CF908G New Year and Original Order

    题意:给 \(n<=10^{700}\) ,问 \(1\)\(n\) 中每个数在各数位排序后得到的数的和,答案对 \(10^9+7\) 取模。

    太久没写数位dp了,调到自闭。感谢 \(\color{black}{\texttt{z}}\color{red}{\texttt{houakngyang}}\) 耐心的指导

    每一个数排序以后可以拆成 \(9\) 个形如 \(111\cdots1\) 数的和(\(223=111+111+1\)

    对于每一个 \(1\le i \le 9\) ,当这一位的值不小于 \(i\) 的时候,\(i\) 所对应的 \(1\) 串长度会增加 \(1\)

    考虑数位dp出 “对于某一个 \(i\) 恰有 \(j\)\(1\)”的数量

    状态开 \(4\) 维,分别表示:在第几位,是否顶到上界,还需要几个不小于 \(i\) 的值,\(i\)

    就可以转移了

    状态总数是 \(n^2*10\) 的,可以通过

    考虑枚举 \(i,j\) 计算答案

    \(ans=\sum\limits_{j=1}^{9}\sum\limits_{i=1}^{n}dp[i][j]*f[j]\)

    \(f[j]\) 表示有 \(j\)\(1\) 的串的值

    我忘记开-Wall导致一个有用变量没用调了一下午

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef double db;
    #define x first
    #define y second
    #define sz(v) (int)v.size()
    #define pb(x) push_back(x)
    #define mkp(x,y) make_pair(x,y)
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=0;c=getchar();}
    	while(isdigit(c))x=x*10+c-'0',c=getchar();
    	return f?x:-x;
    }
    #define N 705
    #define mod 1000000007
    char s[N];
    int d[N],dp[N][N][10];
    void fmod(int&x){x-=mod,x+=x>>31&mod;}
    int qpow(int n,int k){int res=1;for(;k;k>>=1,n=1ll*n*n%mod)if(k&1)res=1ll*n*res%mod;return res;}
    int dfs(int pos,int limit,int sum,int low){
    	if(!pos)return !sum;
    	if(!limit&&~dp[pos][sum][low])return dp[pos][sum][low];
    	int res=0,up=limit?d[pos]:9;
    	for(int i=0;i<=up;++i)fmod(res+=dfs(pos-1,limit&&i==up,sum-(i>=low),low));
    	if(!limit)dp[pos][sum][low]=res;
    	return res;
    }
    int solve(char*s){
    	int res=0;
    	d[0]=0;int n=strlen(s+1);
    	for(int i=1,j=n;i<=n;++i,--j)d[j]=s[i]-'0';
    	for(int i=1;i<=9;++i)
    		for(int j=1,now=1;j<=n;++j,now=(10ll*now+1)%mod)
    			fmod(res+=1ll*dfs(n,1,j,i)*now%mod);
    	return res;
    }
    signed main(){
    	memset(dp,-1,sizeof(dp));
    	scanf("%s",s+1);
    	printf("%d\n",solve(s));
    }