题解:
数位$dp$模板题。
只需要记录上升下降,还有是否在边界上即可。
其中$f,g$是前缀和和后缀和。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 105 #define ll long long #define MOD 1000000007 int T,len; char s[N]; ll dp[N][12][2][2]; ll f[N][12][2][2],g[N][12][2][2]; int main() { scanf("%d",&T); while(T--) { scanf("%s",s+1); len = strlen(s+1); memset(dp,0,sizeof(dp)); memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); for(int i=1;i<=len;i++) { if(i==1) { dp[i][s[i]-'0'][0][0] = 1; for(int j=1;j<s[i]-'0';j++) dp[i][j][1][0]++; }else { if(s[i-1]>s[i]) (dp[i][s[i]-'0'][0][0] += dp[i-1][s[i-1]-'0'][0][0])%=MOD; else if(s[i-1]<s[i]) (dp[i][s[i]-'0'][0][1] += dp[i-1][s[i-1]-'0'][0][1]+dp[i-1][s[i-1]-'0'][0][0])%=MOD; else { (dp[i][s[i]-'0'][0][0] += dp[i-1][s[i-1]-'0'][0][0])%=MOD; (dp[i][s[i]-'0'][0][1] += dp[i-1][s[i-1]-'0'][0][1])%=MOD; } for(int j=1;j<=9;j++) dp[i][j][1][0]++; } for(int j=0;j<s[i]-'0';j++) { (dp[i][j][1][0]+=g[i-1][j][0][0])%=MOD; (dp[i][j][1][1]+=f[i-1][j][0][0]+f[i-1][j][0][1]-dp[i-1][j][0][0])%=MOD; } for(int j=0;j<=9;j++) { (dp[i][j][1][0]+=g[i-1][j][1][0])%=MOD; (dp[i][j][1][1]+=f[i-1][j][1][0]+f[i-1][j][1][1]-dp[i-1][j][1][0])%=MOD; } for(int j=0;j<=9;j++) { f[i][j][0][0]=(f[i][j-1][0][0]+dp[i][j][0][0])%MOD; f[i][j][0][1]=(f[i][j-1][0][1]+dp[i][j][0][1])%MOD; f[i][j][1][0]=(f[i][j-1][1][0]+dp[i][j][1][0])%MOD; f[i][j][1][1]=(f[i][j-1][1][1]+dp[i][j][1][1])%MOD; } for(int j=9;j>=0;j--) { g[i][j][0][0]=(g[i][j+1][0][0]+dp[i][j][0][0])%MOD; g[i][j][0][1]=(g[i][j+1][0][1]+dp[i][j][0][1])%MOD; g[i][j][1][0]=(g[i][j+1][1][0]+dp[i][j][1][0])%MOD; g[i][j][1][1]=(g[i][j+1][1][1]+dp[i][j][1][1])%MOD; } } ll ans = ((f[len][9][0][0]+f[len][9][0][1]+f[len][9][1][0]+f[len][9][1][1])%MOD+MOD)%MOD; printf("%lld ",ans); } return 0; }