题目链接:http://codeforces.com/problemset/problem/908/G
题解:dp[i][j][x][l]代表前i个数中有j个数>=x, l代表是否已经抵达n这个数的边界。
num = dp[i][j][x][0]+dp[i][j][x][1]代表前i个数中有j个数>=x的总方案数。
如果某一位上为3,则3>=1, 3>=2, 3>=3的时候, 考虑了3次,所以可以看做排序后的最后j个数全为1.
所以num*111111(共j个1)代表前i个数中有j个数>=x的值。
#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int MX = 707;
int dp[MX][MX][10][2];
int a[MX];
char s[MX];
const int mod = 1e9+7;
int main()
{
scanf("%s",s+1);
int n = strlen(s+1);
for(int i = 1; i <= n; i++)
a[i] = s[i] - '0';
// cout<<a[1]<<" "<<a[2]<<endl;
for(int i = 1; i <= 9; i++) dp[0][0][i][1] = 1;
for(int x = 1; x <= 9; x++)
for(int i = 0; i < n; i++)
for(int j = 0; j <= i; j++)
for(int l = 0; l < 2; l++)
for(int p = 0; p <= (!l? 9 : a[i+1]); p++)
(dp[i+1][j+(p>=x)][x][l&(p==a[i+1])] += dp[i][j][x][l])%=mod;
LL res = 0;
for(int i = 1; i <= 9; i++){
LL temp = 1;
for(int j = 1; j <= n; j++)
res = (res+(dp[n][j][i][0]+dp[n][j][i][1])*temp%mod)%mod, temp = (temp*10+1)%mod;
}
cout<<res<<endl;
return 0;
}