吉哥系列故事——恨7不成妻
Time Limit: 1000/500 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1117 Accepted Submission(s): 336
Problem Description
单身!
依然单身!
吉哥依然单身!
DS级码农吉哥依然单身!
所以,他生平最恨情人节,不管是214还是77,他都讨厌!
吉哥观察了214和77这两个数,发现:
2+1+4=7
7+7=7*2
77=7*11
最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数!
什么样的数和7有关呢?
如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——
1、整数中某一位是7;
2、整数的每一位加起来的和是7的整数倍;
3、这个整数是7的整数倍;
现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
Input
输入数据的第一行是case数T(1 <= T <= 50),然后接下来的T行表示T个case;每个case在一行内包含两个正整数L, R(1 <= L <= R <= 10^18)。
Output
请计算[L,R]中和7无关的数字的平方和,并将结果对10^9 + 7 求模后输出。
Sample Input
Sample Output
Source
2013腾讯编程马拉松初赛第一场(3月21日)
Recommend
liuyiding | We have carefully selected several similar problems for you: 4769 4768 4767 4766 4765
挺明显的数位DP,学习了kuangbin大神的写法:http://www.cnblogs.com/kuangbin/archive/2013/05/01/3053233.html
思路是对应于题目的三个要求,我们去维护三个数:
1.与7无关的数
2.与7无关的数的和 --- 维护一个sum,每次加上p[pos] * i * 后面的数dfs
3.与7无关的数的平方和 ---维护一个sqsum,需要用到前面两个
(pre*10^pos + next)^2= (pre*10^pos)^2+2*pre*10^pos*next +next^2
/*
ID: xinming2
PROG: stall4
LANG: C++
*/
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
using namespace std;
///#define Online_Judge
#define outstars cout << "***********************" << endl;
#define clr(a,b) memset(a,b,sizeof(a))
#define lson l , mid , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define mk make_pair
#define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++)
#define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++)
#define REP(i , x , n) for(int i = (x) ; i > (n) ; i--)
#define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--)
const int MAXN = 100000 + 50;
const int sigma_size = 26;
const long long LLMAX = 0x7fffffffffffffffLL;
const long long LLMIN = 0x8000000000000000LL;
const int INF = 0x7fffffff;
const int IMIN = 0x80000000;
#define eps 1e-8
const int mod = (int)1e9 + 7;
typedef long long LL;
const LL MOD = 1000000007LL;
const double PI = acos(-1.0);
typedef pair<int , int> pi;
#define Bug(s) cout << "s = " << s << endl;
///#pragma comment(linker, "/STACK:102400000,102400000")
struct Num
{
LL cnt;///与7无关的个数
LL sum;///与7无关的个数和
LL sqsum;///平方和
}dp[20][20][20];///dp[i][j][k]表示处理的位数,数字和%7,数字%7
int digit[20];
LL p[20];///p[i] = 10^ i;
Num dfs(int pos , int pre1 , int pre2, bool fp)
{
if(pos == -1)
{
Num tmp;
tmp.cnt = (pre1 != 0) && (pre2 != 0);
tmp.sum = tmp.sqsum = 0;
return tmp;
}
if(!fp && dp[pos][pre1][pre2].cnt != -1)return dp[pos][pre1][pre2];
int maxi = fp ? digit[pos] : 9;
Num ans , tmp;
ans.cnt = ans.sqsum = ans.sum = 0;
for(int i = 0 ; i <= maxi ; i++)
{
if(i == 7)continue;
tmp = dfs(pos - 1 , (pre1 + i) % 7 , (pre2 * 10 + i)% 7 , fp && i == maxi);
ans.cnt += tmp.cnt;
ans.cnt %= MOD;
ans.sum += (tmp.sum + ((p[pos] * i) % MOD) * tmp.cnt % MOD) % MOD;
ans.sum %= MOD;
ans.sqsum += (tmp.sqsum + ((2 * p[pos] * i) % MOD) *tmp.sum) % MOD;///next^2 + 2*pre*10^pos*next
ans.sqsum %= MOD;
ans.sqsum += (tmp.cnt * p[pos]) % MOD * p[pos] % MOD * i * i % MOD;///(pre*10^pos)^2
ans.sqsum %= MOD;
}
if(!fp)dp[pos][pre1][pre2] = ans;
return ans;
}
LL f(LL n)
{
int len = 0;
while(n)
{
digit[len++] = n % 10;
n /= 10;
}
return dfs(len - 1, 0 , 0 , 1).sqsum;
}
int main()
{
int T;
LL a , b;
p[0] = 1;
for(int i = 1 ; i < 20 ; i++)
{
p[i] = (p[i - 1] * 10) % MOD;
}
for(int i = 0 ; i < 20 ; i++)
{
for(int j = 0 ; j < 10 ; j++)
{
for(int k = 0 ; k < 10 ; k++)
{
dp[i][j][k].cnt = -1;
}
}
}
scanf("%d" , &T);
while(T--)
{
scanf("%I64d%I64d" , &a , &b);
LL ans = f(b) - f(a - 1);
printf("%I64d\n" , (ans % MOD + MOD ) % MOD);
}
return 0;
}