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

    题意

    给你一个数(n),另(S(x))表示(x)中各位数从小到大排序后的数,例如(S(120542)=12245)
    (sum_{i=1}^n S(i))

    (1 le n le 10^{700})

    传送门

    思路

    首先肯定是一道数位dp

    考虑将某位数的贡献(x imes 10^i)转化为(x)(10^i)相加,设(dp[i][j][k][0/1])表示前(i)位中有(j)位的数字大于等于(k),是否等于(n)的方案数。

    转移很显然(dp[i][j+(now ge k)][k][h &(now==n[i])]+=dp[i-1][j][k][h])

    考虑计算答案,对于(dp[n][i][j][0/1])(j)位的数都会产生贡献,加起来就是(underbrace{111cdots11}_{j ext{个}1})。那么对于某个数(x),当(1le i le x)的时候都会计算到一次,所以累计就是答案。

    #include <bits/stdc++.h>
    const int mu=1e9+7;
    int dp[705][705][10][2],ans;
    char s[705];
    void reduce(int &x) { x+=x>>31&mu; }
    int main(){
    	scanf("%s",s);
    	int l=strlen(s);
    	for (int i=1;i<=9;i++) dp[0][0][i][1]=1;
    	for (int i=1;i<=l;i++)
    		for (int j=0;j<i;j++)
    			for (int k=1;k<=9;k++)
    				for (int h=0;h<=1;h++){
    					int t=dp[i-1][j][k][h];
    					if (!t) continue;
    					for (int now=0;now<=9;now++){
    						if(h==1 && now>s[i-1]-'0') break;
    						reduce(dp[i][j+(now>=k)][k][h&(now==s[i-1]-'0')]+=t-mu);
    					}		
    				}
    	for (int i=1;i<=9;i++){
    		for (int j=1,t=1;j<=l;j++,t=(t*10ll+1)%mu)
    			ans=(ans+1ll*t*(dp[l][j][i][0]+dp[l][j][i][1]))%mu;
    	}
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    静态代码块执行时机
    java中的命令
    JDBC
    final, finally, finalize
    面向对象
    线程中常用的一些方法
    线程中的yield()
    线程中的join()
    Thread对象 既传入了Runnable对象又重写了run()方法
    Python 绘制词云
  • 原文地址:https://www.cnblogs.com/flyfeather6/p/13226864.html
Copyright © 2011-2022 走看看