解题思路:数位dp。可以将1~9每一位出现的次数统计一下,再对应相乘之后再加。从高位向低位搜,dp[i][j]还剩下j位的时候,前面走了i个x,的数量是多少个。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double lf;
typedef unsigned long long ull;
typedef pair< int , int > P;
const int inf = 0x7f7f7f7f ;
const ll INF = 1e16 ;
const int N = 2e5 + 10 ;
const ull base = 131 ;
const ll mod = 1e9 + 7 ;
inline int read ( ) { int x= 0 , f= 1 ; char ch= getchar ( ) ; while ( ch< '0' || ch> '9' ) { if ( ch== '-' ) f= - 1 ; ch= getchar ( ) ; } while ( ch>= '0' && ch<= '9' ) { x= x* 10 + ch- '0' ; ch= getchar ( ) ; } return x* f; }
inline string readstring ( ) { string str; char s= getchar ( ) ; while ( s== ' ' || s== '\n' || s== '\r' ) { s= getchar ( ) ; } while ( s!= ' ' && s!= '\n' && s!= '\r' ) { str+ = s; s= getchar ( ) ; } return str; }
int random ( int n) { return ( int ) ( rand ( ) * rand ( ) ) % n; }
void writestring ( string s) { int n = s. size ( ) ; for ( int i = 0 ; i < n; i++ ) { printf ( "%c" , s[ i] ) ; } }
bool is_prime ( int n) { if ( n < 2 ) return false; for ( int i = 2 ; i* i <= n; i++ ) { if ( n% i == 0 ) return false; } return true; }
int a[ 50 ] ;
ll dp[ 50 ] [ 50 ] ;
ll dfs ( int pos, int ret, int ok, int flag) {
if ( pos < 1 ) return ret;
if ( ! ok&& dp[ ret] [ pos] != - 1 ) return dp[ ret] [ pos] ;
int last = ok? a[ pos] : 9 ;
ll sum = 0 ;
for ( int i = 0 ; i <= last; i++ ) {
sum + = dfs ( pos- 1 , ret+ ( i== flag) , ok&& i== last, flag) ;
sum % = mod;
}
if ( ! ok) dp[ ret] [ pos] = sum;
return sum;
}
ll solve ( ll n, int flag) {
int pos = 0 ;
memset ( dp, - 1 , sizeof dp) ;
while ( n) {
a[ ++ pos] = n% 10 ;
n / = 10 ;
}
return dfs ( pos, 0 , 1 , flag) ;
}
void fun ( ) {
ll l, r; cin >> l >> r;
ll ans = 0 ;
for ( int i = 1 ; i <= 9 ; i++ ) {
ans = ( ans+ ( i* solve ( r, i) ) % mod) % mod;
}
for ( int i = 1 ; i <= 9 ; i++ ) {
ans = ( ans- ( i* solve ( l- 1 , i) ) % mod+ mod) % mod;
}
while ( ans < 0 ) {
ans = ( ans+ mod) % mod;
}
cout<< ans<< endl;
}
int main ( ) {
int t = read ( ) ;
while ( t-- ) {
fun ( ) ;
}
return 0 ;
}