之前的博客中提到过CF1073E,现在重新回顾一下这种类型的题目。均是求L-R的区间中符合类型的数的和,而不是求符合类型的数的数量。
P4950 完美数字
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N= 10 ;
int T, n, m, x, now, p1, p2;
int a[ N] , g[ N] [ 1 << 10 ] , f[ N] [ 1 << 10 ] , inv[ N] ;
struct node{ int num, sum; } ;
node dfs ( int x, int p, int lead, int limit)
{
if ( x== 0 )
{
if ( lead) return ( node) { 0 , 0 } ;
else if ( ( p& p1) == p1 && ( p& p2) == 0 ) return ( node) { 1 , 0 } ;
else return ( node) { 0 , 0 } ;
}
if ( ! lead && ! limit && g[ x] [ p] != - 1 ) return ( node) { g[ x] [ p] , f[ x] [ p] } ;
int h;
if ( limit) h= a[ x] ; else h= 9 ;
node res, now;
res. num= res. sum= now. num= now. sum= 0 ;
for ( register int i= 0 ; i<= h; ++ i)
{
if ( lead && ( i== 0 ) )
{
now= dfs ( x- 1 , p, 1 , ( i== h) && limit) ;
res. num+ = now. num;
res. sum+ = now. sum;
res. sum+ = i* inv[ x] * now. num;
continue ;
}
if ( ( 1ll << i) & p2) continue ;
now= dfs ( x- 1 , p| ( 1ll << i) , 0 , ( i== h) && limit) ;
res. num+ = now. num;
res. sum+ = now. sum;
res. sum+ = i* inv[ x] * now. num;
}
if ( ! limit && ! lead)
{
g[ x] [ p] = res. num;
f[ x] [ p] = res. sum;
}
return res;
}
inline int solve ( int x)
{
int len= 0 ;
while ( x)
{
a[ ++ len] = x% 10 ;
x/ = 10 ;
}
return dfs ( len, 0 , 1 , 1 ) . sum;
}
signed main ( ) {
inv[ 1 ] = 1 ;
for ( register int i= 2 ; i<= 10 ; ++ i) inv[ i] = inv[ i- 1 ] * 10 ;
scanf ( "%lld" , & T) ;
while ( T-- )
{
memset ( g, - 1 , sizeof ( g) ) ;
scanf ( "%lld%lld" , & n, & m) ;
p1= p2= 0 ;
scanf ( "%lld" , & x) ;
while ( x-- ) scanf ( "%lld" , & now) , p1| = 1ll << now;
scanf ( "%lld" , & x) ;
while ( x-- ) scanf ( "%lld" , & now) , p2| = 1ll << now;
printf ( "%lld\n" , solve ( m) - solve ( n- 1 ) ) ;
}
return 0 ;
}
CF1073E Segment Sum
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N= 20 , MOD= 998244353 ;
int n, m, k;
int a[ N] , g[ N] [ 1 << 10 ] , f[ N] [ 1 << 10 ] , inv[ N] ;
struct node{ int num, sum; } ;
node dfs ( int x, int p, int cnt, int lead, int limit)
{
if ( x== 0 )
{
if ( lead) return ( node) { 0 , 0 } ;
else return ( node) { 1 , 0 } ;
}
if ( ! lead && ! limit && g[ x] [ p] != - 1 ) return ( node) { g[ x] [ p] , f[ x] [ p] } ;
int h;
if ( limit) h= a[ x] ; else h= 9 ;
node res, now;
res. num= res. sum= now. num= now. sum= 0 ;
for ( register int i= 0 ; i<= h; ++ i)
{
if ( cnt== k && ( ( 1ll << i) & p) == 0 ) continue ;
if ( lead && ( i== 0 ) )
{
now= dfs ( x- 1 , p, cnt, 1 , ( i== h) && limit) ;
res. num= ( res. num+ now. num) % MOD;
res. sum= ( res. sum+ now. sum) % MOD;
res. sum= ( res. sum+ i* inv[ x] % MOD* now. num% MOD) % MOD;
}
else
{
now= dfs ( x- 1 , p| ( 1ll << i) , cnt+ ( ( ( 1ll << i) & p) == 0 ) , 0 , ( i== h) && limit) ;
res. num= ( res. num+ now. num) % MOD;
res. sum= ( res. sum+ now. sum) % MOD;
res. sum= ( res. sum+ i* inv[ x] % MOD* now. num% MOD) % MOD;
}
}
if ( ! limit && ! lead)
{
g[ x] [ p] = res. num;
f[ x] [ p] = res. sum;
}
return res;
}
inline int solve ( int x)
{
memset ( g, - 1 , sizeof ( g) ) ;
int len= 0 ;
while ( x)
{
a[ ++ len] = x% 10 ;
x/ = 10 ;
}
return dfs ( len, 0 , 0 , 1 , 1 ) . sum;
}
signed main ( ) {
scanf ( "%lld%lld%lld" , & n, & m, & k) ;
inv[ 1 ] = 1 ;
for ( register int i= 2 ; i<= 20 ; ++ i) inv[ i] = inv[ i- 1 ] * 10 % MOD;
printf ( "%lld\n" , ( ( solve ( m) - solve ( n- 1 ) ) % MOD+ MOD) % MOD) ;
return 0 ;
}