传送门:【HDU】4507 吉哥系列故事——恨7不成妻
题目分析:状态限制条件要多,保证不会重叠。dp用结构体表示,记录当前状态下符合条件的数的个数,数和,数平方和。然后由于数是可以递推的,于是这题可数位DP了。具体怎么推也不难,自己思考下吧~
数位DP还有好多题没写,论文也还没看,找个时间再看吧。。。
希望在上海赛之前还能有所提高~
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; #define rep( i , a , b ) for ( int i = a ; i < b ; ++ i ) #define For( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define rev( i , a , b ) for ( int i = a ; i >= b ; -- i ) #define clr( a , x ) memset ( a , x , sizeof a ) const int mod = 1e9 + 7 ; struct Node { LL num , sum , sqr ; Node () {} Node ( LL num , LL sum , LL sqr ) : num ( num ) , sum ( sum ) , sqr ( sqr ) {} } dp[20][2][7][7] ; int vis[20][2][7][7] , Time ; int digit[20] ; LL pow[20] ; Node dfs ( int cur , int limit , int t1 , int t2 , int t3 ) { if ( !cur ) return Node ( !t1 && t2 && t3 , 0 , 0 ) ; if ( vis[cur][t1][t2][t3] == Time && !limit ) return dp[cur][t1][t2][t3] ; vis[cur][t1][t2][t3] = Time ; Node ans = Node ( 0 , 0 , 0 ) ; int n = limit ? digit[cur] : 9 ; For ( i , 0 , n ) { int a = t1 || i == 7 , b = ( t2 * 10 + i ) % 7 , c = ( t3 + i ) % 7 ; LL tmp = i * pow[cur - 1] % mod ; Node pre = dfs ( cur - 1 , limit && i == digit[cur] , a , b , c ) ; LL num = ( ans.num + pre.num ) % mod ; LL sum = ( ans.sum + pre.sum + tmp * pre.num ) % mod ; LL sqr = ( ans.sqr + pre.num * tmp % mod * tmp + 2 * tmp * pre.sum + pre.sqr ) % mod ; ans = Node ( num , sum , sqr ) ; } if ( !limit ) dp[cur][t1][t2][t3] = ans ; return ans ; } LL cal ( LL n ) { int n1 = 0 ; LL tmp = n ; while ( tmp ) { digit[++ n1] = tmp % 10 ; tmp /= 10 ; } ++ Time ; ; return dfs ( n1 , 1 , 0 , 0 , 0 ).sqr ; } void solve () { LL L , R ; scanf ( "%I64d%I64d" , &L , &R ) ; printf ( "%I64d\n" , ( cal ( R ) - cal ( L - 1 ) + mod ) % mod ) ; } int main () { int T ; pow[0] = 1 ; rep ( i , 1 , 20 ) pow[i] = pow[i - 1] * 10 % mod ; clr ( vis , 0 ) ; Time = 0 ; scanf ( "%d" , &T ) ; while ( T -- ) solve () ; return 0 ; }