zoukankan      html  css  js  c++  java
  • 【CF908G】New Year and Original Order 数位DP

    【CF908G】New Year and Original Order

    题意:令S(i)表示将i中所有数位上的数拿出来,从小到大排序后组成一个新的数的值。如S(50394)=3459。求$sumlimits_{i=1}^nS(i)$。

    $nle 10^{700}$。

    题解:比较难的数位DP。我们考虑分别计算每个数字的贡献。令f0[i][a][b]表示考虑到第i位数,其中数字a的最高为是b的数的数量,再令f1[i][a][b]表示a这个数的贡献。再设g0,g1表示小于等于n的所有数的DP值。转移比较复杂,我能1A也是不容易啊。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    const ll P=1000000007;
    int n;
    int v[705];
    ll ans;
    ll f0[705][10][705],f1[705][10][705],g0[705][10][705],g1[705][10][705],pw[705];
    char str[705];
    int main()
    {
    	int i,a,b,j;
    	scanf("%s",str),n=strlen(str);
    	for(pw[0]=i=1;i<=n;i++)	v[i]=str[n-i]-'0',pw[i]=pw[i-1]*10%P;
    	for(a=0;a<=9;a++)	f0[0][a][0]=g0[0][a][0]=1;
    	for(i=1;i<=n;i++)	for(a=0;a<=9;a++)	for(b=0;b<=9;b++)
    	{
    		if(b==8)
    		{
    			b++,b--;
    		}
    		if(a<b)	for(j=0;j<i;j++)
    		{
    			f1[i][b][j]=(f1[i][b][j]+f1[i-1][b][j])%P;
    			f0[i][b][j]=(f0[i][b][j]+f0[i-1][b][j])%P;
    			if(a<v[i])
    			{
    				g1[i][b][j]=(g1[i][b][j]+f1[i-1][b][j])%P;
    				g0[i][b][j]=(g0[i][b][j]+f0[i-1][b][j])%P;
    			}
    			else if(a==v[i])
    			{
    				g1[i][b][j]=(g1[i][b][j]+g1[i-1][b][j])%P;
    				g0[i][b][j]=(g0[i][b][j]+g0[i-1][b][j])%P;
    			}
    		}
    		else	if(a==b)	for(j=0;j<i;j++)
    		{
    			f1[i][b][j+1]=(f1[i][b][j+1]+f1[i-1][b][j]+f0[i-1][b][j]*a*pw[j])%P;
    			f0[i][b][j+1]=(f0[i][b][j+1]+f0[i-1][b][j])%P;
    			if(a<v[i])
    			{
    				g1[i][b][j+1]=(g1[i][b][j+1]+f1[i-1][b][j]+f0[i-1][b][j]*a*pw[j])%P;
    				g0[i][b][j+1]=(g0[i][b][j+1]+f0[i-1][b][j])%P;
    			}
    			else if(a==v[i])
    			{
    				g1[i][b][j+1]=(g1[i][b][j+1]+g1[i-1][b][j]+g0[i-1][b][j]*a*pw[j])%P;
    				g0[i][b][j+1]=(g0[i][b][j+1]+g0[i-1][b][j])%P;
    			}
    		}
    		else	for(j=0;j<i;j++)
    		{
    			f1[i][b][j+1]=(f1[i][b][j+1]+f1[i-1][b][j]*10)%P;
    			f0[i][b][j+1]=(f0[i][b][j+1]+f0[i-1][b][j])%P;
    			if(a<v[i])
    			{
    				g1[i][b][j+1]=(g1[i][b][j+1]+f1[i-1][b][j]*10)%P;
    				g0[i][b][j+1]=(g0[i][b][j+1]+f0[i-1][b][j])%P;
    			}
    			else if(a==v[i])
    			{
    				g1[i][b][j+1]=(g1[i][b][j+1]+g1[i-1][b][j]*10)%P;
    				g0[i][b][j+1]=(g0[i][b][j+1]+g0[i-1][b][j])%P;
    			}
    		}
    	}
    	for(a=0;a<=9;a++)	for(i=1;i<=n;i++)	ans=(ans+g1[n][a][i])%P;
    	printf("%lld",ans);
    	return 0;
    }
  • 相关阅读:
    MVC模型验证
    AutoMapper完成Dto与Model的转换
    【转】Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案
    MVC过滤器详解
    IOC框架Ninject实践总结
    【转】NHibernate对象以及状态说明
    轻量级IOC框架:Ninject (上)
    mysql5.7 误删管理员root账户
    杂项
    X-Pack权限控制之给Kibana加上登录控制以及index_not_found_exception问题解决
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8227419.html
Copyright © 2011-2022 走看看