这题在每次DFS的时候要返回 平方和、和、构成这个平方和的数的个数,具体原因在下面有。
DFS( int pos, int sum, int number, bool flag ) 表示进行到第pos位, 各位数之和为 sum ,数为 number 状态为flag
现在解释 为什么DFS要像上面所说的一样来返回值
首先 这样能够返回平方和 ,这是要求的。
然后这只是卖个萌。。。。。
其实 我们每次DFS返回了 pos位之后的位置 组成的满足要求的数 的平方和、和、构成这个平方和的数的个数 然后我们再结合此时的这个 i 来继续向上返回值 向上返回值得公式在代码中。
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
struct Node{
__int64 n, sum, sumpow;
Node() : n(0), sum(0), sumpow(0){}
}dp[20][7][7];
int digit[20];
int len;
const int K = 1000000000 + 7;
__int64 p[20];
void init( __int64 N ){
digit[0] = 0;
while( N ){
digit[++digit[0]] = N % 10;
N /= 10;
}
}
Node DFS( int pos, int sum, int number, bool flag ){
Node n, s;
if( pos == 0 ){
s.n = sum && number;
return s;
}
if( flag && dp[pos][sum][number].n != -1 ){
return dp[pos][sum][number];
}
int end = flag ? 9 : digit[pos];
for( int i = 0; i <= end; i++ ){
if( i == 7 ){
continue;
}
n = DFS( pos - 1, ( sum + i ) % 7, ( number * 10 + i ) % 7, flag || i < end );
s.n += n.n;
s.n %= K;
// i * p + x1 + i * p + x2 + i * P + x3 ..... = i * p * n + sum
s.sum += ( p[pos-1] * i % K * n.n + n.sum );
s.sum %= K;
// i * i * p * p + 2 * x1 * p + x1 * x1 +.....= p * p * i * i * n + 2 * sum * p + sumpow
s.sumpow += ( p[pos-1] * p[pos-1] % K * i * i % K * n.n + 2 * p[pos-1] * i % K * n.sum + n.sumpow );
s.sumpow %= K;
}
if( flag ){
dp[pos][sum][number] = s;
}
return s;
}
int main(){
p[0] = 1;
for( int i = 1; i < 20; i++ ){
p[i] = ( p[i-1] * 10 ) % K;
}
memset( dp, -1, sizeof dp );
int T;
cin >> T;
while( T-- ){
__int64 L, R;
cin >> L >> R;
init( R );
__int64 b = DFS( digit[0], 0, 0, false ).sumpow;
init( L - 1 );
__int64 a = DFS( digit[0], 0, 0, false ).sumpow;
cout << ( b - a + K ) % K << endl;
}
return 0;
}