この質問の考え方は難しくありませんが、正しく計算することは非常に困難です。モジュロはあまりにうんざりしているため、いつでもオーバーフローします。また、モジュロのレベルが低いため、モジュロを取る前に乗算を防ぐために複数のブラケットを使用する必要があります。
要するに、係数はどこでも取られ、C ++の係数は負になる可能性があるため、負にならないようにmodを記述する必要があります。
練習自体はデジタルdpであり、ここでは平方和が必要です。通常、以前に行うことは数を見つけることです。数を見つける方法によれば、この質問はfとして設計する必要があります[] [] [] []は最初のiを意味します、最高ビットはjを書き込み、整数mod7の残りはkで、すべてのビットの合計の残りはlです。
しかし、この質問では平方和が必要です。すべての数値はj * 10 ^(i-1)+ Aで表すことができることはわかっています。このAは、最上位ビットを除いた数値のサイズを表します。このように、高校で学習した正方形を拡張することで、この式を見つけるには、数値、1ビットの合計、および平方和を保存する必要があることがわかります。
拡大により、前処理の状態を知ることができます。
それは主に嫌で、本当に嫌です
#include <iostream> #include <vector> #include <algorithm> #include <cstring> using namespace std; typedef long long ll; const int N = 20 ; const int p = 1e9 + 7 ; struct node { ll s1; ll s2; ll s3; } f [N] [ 10 ] [ 8 ] [ 8 ]; int power7 [N]、power9 [N]; int mod(ll a、int b){ return(a%b + b)%b; } void init(){ int i、j、k、l、r; for(i = 0 ; i <= 9 ; i ++ ){ if(i == 7 ) 続行; f [ 1 ] [i] [i%7 ] [i%7 ] .s1 + = 1 ; f [ 1 ] [i] [i%7 ] [i%7 ] .s2 + = i; f [ 1 ] [i] [i%7 ] [i%7 ] .s3 + = i * i; } ll power = 10 ; for(i = 2 ; i <N; i ++、power * = 10 ){ for(j = 0 ; j <= 9 ; j ++ ){ if(j == 7 ) continue ; for(k = 0 ; k < 7 ; k ++ ){ for(l = 0 ; l < 7 ; l ++ ){ for(r = 0 ; r <= 9 ; r ++ ){ if(r == 7 ) 続行; 自動&v1 = f [i] [j] [k] [l]、&v2 = f [i- 1 ] [r] [mod(k-j * power、7)] [mod(l-j、7 )] ; v1.s1 = mod(v1.s1 + v2.s1、p); v1.s2 = mod(v1.s2 + j *(power%p)%p * v2.s1%p + v2.s2、p); // v1.s3 = mod(v1.s3 + j * j *(power%p)%p *(power%p)%p * v2.s1 + v2.s3 + // 2 * j * power%p * v2.s2、p); v1.s3 = mod(v1.s3 + j *(power%p)%p *(power%p)%p * j *(v2.s1%p)+ 2 * j * power%p * v2.s2% p + v2.s3、p); } } } } } power7 [ 0 ] = 1 ; for(int i = 1 ; i <N; i ++)power7 [i] = power7 [i- 1 ] * 10%7 ; power9 [ 0 ] = 1 ; for(int i = 1 ; i <N; i ++)power9 [i] = power9 [i- 1 ] * 10ll%p; } node get(int i、int j、int a、int b){ int s3 =0、s1 = 0、s2 = 0 ; for(int x = 0 ; x < 7 ; x ++ ) for(int y = 0 ; y < 7 ; y ++ ) if(x!= a && y!= b) { auto v = f [i] [j] [x] [y]; s1 =(s1 + v.s1)%p; s2 =(s2 + v.s2)%p; s3 =(s3 + v.s3)%p; } 返し{s1、s2、s3}; } ll dp(ll n){ if(!n) return 0 ; vector < int > num; ll符号 = n%p; while (n){ num.push_back(n%10 ); n / = 10 ; } ll res = 0 ; ll last1 = 0 ; ll last2 = 0 ; int i; for(i = num.size()- 1 ; i> = 0 ; i-- ){ int x = num [i]; int j; for(j = 0 ; j <x; j ++ ){ if(j == 7 ) continue ; int a = mod(-last1 * power7 [i + 1 ]、7 ); INT B = MOD(-last2、7 )。 auto v = get(i + 1 、j、a、b); res = mod( res + (last1%p)*(last1%p)%p * power9 [i + 1 ]%p * power9 [i + 1 ]%p * v.s1%p + v.s3 + 2 * last1%p * power9 [i + 1 ]%p * v.s2、 p); } if(x == 7 ) break ; last1 = 10 * last1 + x; last2 + = x; if(!I &&(last1%7)&&(last2%7 )) { res = mod(res + sign%p * sign%p、p); // moduloの優先度に注意を払わない限り、符号が一度も取得されない場合、ここでオーバーフローします } } 解像度を返す。 } int main(){ ll l、r; int t; cin >> t; 初期化(); while(t-- ){ cin >> l >> r; cout << mod(dp(r)-dp(l- 1)、p)<< endl; } }