【Hdu】4705 恨7不成妻

哇乍一看这题怎么这么水啊,但是我看到了最后一行的时候才发现其实不然(滑稽)

 

它要求的答案是所有数的平方和!!!

 

首先裸裸的数位 Dp 求出了满足条件的数的个数(定义 dp [ 位数 ] [ 每位和%7 ] [ 数值%7 ]),记为 Cnt,那么我们现在考虑如何将答案给搞出来吧!

 

我们可以利用 Dfs 的步骤,考虑将第 Dep 位的答案用 Dep 减1位更新

 

首先很好更新的是前 Dep 位的所有合法数字和,我们考虑所有数字的和一定可以拆分成:

Y{_1}10 ^ {X{_1}} + Y{_2}10 ^ {X{_1}-1} +......

所以显然第 Dep 位数为 i 时对于答案的贡献就是 i *(Dfs 下一位所得到的合法数的个数)* (10 的 Dep 次方),记为 Sum

 

其次考虑如何更新 Dep 位对于平方和的贡献啦!首先前 Dep 位组成的一个数的平方一定是:

Sum{_s_i_n_g_l_e}^{2}=(i10^{Dep}+Sum{_o_f_D_e_p_-_1})^{2}

Sum{_{single}}^{2}=i^{2}10^{2Dep}+2iSum{_{of Dep-1}}+Sum{_{ofDep-1}}^{2}

 

由于我们只用加上 i 对当前位的贡献,所以这个时候我们只用关心与当前位 i 有关的东西,Sum{_{ofDep-1}}^{2} 管都不用管,直接展开换成 Sum{_{all}} 就好啦!

那么 Cnt 个数呢?这个时候 Dep 位 i^{2}10^{2Dep} 的贡献就多了 Cnt 倍,对吧,所以

SquareSum_{Dep}=(i10^{Dep})^2Cnt+2*i*10^{len}*Sum{_{ofDep-1}}+SquareSum_{Dep-1}

 

推就是了

 

AC码:

 

# include <bits/stdc++.h>

const  long long  mod = 1e9 + 7 ;

long long  powx [ 30 ] , dig [ 30 ] , x , y ;
int  T ; 

struct  Node {
    long long  cnt , sum , sqs ;
}
dp [ 25 ] [ 20 ] [ 20 ] ;


Node  dfs ( int  dep , int  res , int  num , int  lim ) {
    if ( dep == 0 ) {
        Node  tmp = ( Node ) { 0 , 0 , 0 } ;
        if ( num != 0  &&  res != 0 )  tmp . cnt = 1 ;
        return  tmp ;
    }
    if ( ! lim  &&  dp [ dep ] [ res ] [ num ] . cnt != - 1 )  return  dp [ dep ] [ res ] [ num ] ;
    long long  i = lim ? dig [ dep ] : 9 ;
    Node  ans ;
    ans . cnt = ans . sum = ans . sqs = 0 ;
    for ( ; i >= 0 ; i -- ) {
        if ( i != 7 ) {
            Node  tmp = dfs ( dep - 1 , ( res * 10 + i ) % 7 , ( num + i ) % 7 , lim  &&  i == dig [ dep ] ) ;
            ans . cnt = ( ans . cnt + tmp . cnt ) % mod ;
            ans . sum = ( ( ans . sum + ( i * powx [ dep - 1 ] % mod * tmp . cnt ) % mod ) % mod + tmp . sum ) % mod ;
            ans . sqs = ( ( ans . sqs + tmp . sqs + ( 2 * i * powx [ dep - 1 ] % mod * tmp . sum ) % mod ) % mod + ( i * powx [ dep - 1 ] % mod * tmp . cnt % mod * powx [ dep - 1 ] % mod * i % mod ) % mod ) % mod ;
        }
    }
    if ( ! lim )  dp [ dep ] [ res ] [ num ] = ans ;
    return  ans ;
}

long long  solve ( long long  x ) {
    memset ( dp , - 1 , sizeof ( dp ) ) ;
    int  cnt = 0 ; 
    while ( x ) {
        dig [ ++ cnt ] = x % 10 ; 
        x /= 10 ; 
    }
    return  dfs ( cnt , 0 , 0 , 1 ) . sqs ;
}

void  init ( ) {
    powx [ 0 ] = 1 ;
    for ( int  i = 1 ; i <= 19 ; i ++ )
        powx [ i ] = ( 1ll * powx [ i - 1 ] * 10 ) % mod ;
}

int  main ( ) {
    init ( ) ;
    scanf ( "%d" , & T ) ;
    for ( int  i = 1 ; i <= T ; i ++ ) {
        std :: cin >> x >> y ;
        std :: cout << ( ( solve ( y ) - solve ( x - 1 ) ) % mod + mod ) % mod << std :: endl;
    }
    return  0 ; 
}

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值