吉哥系列故事——恨7不成妻 hdu4507

数位DP, 继续练习记忆化搜索的数位DP写法,状态转移需要推导一下,

是依据这个性质

(a+b1)^2+(a+b2)^2+...(a+bn)^2 = n*a^2+2*a*(b1+b2+...bn)+b1^2+b2^2+...bn^2



#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string>    
#include <sstream>
#include <utility>   
#include <ctime>

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;

const int MAXN(2010);
const int SIGMA_SIZE(2);
const int MAXM(110);
const int MAXE(300010);
const int MAXH(18);
const int INFI((INT_MAX-1) >> 1);
const int MOD(1000000007);
const ULL LIM(1000000000000000ull);

struct ELE
{
    LL qua, suf1, suf2;   //从当前状态能够到达合法叶子节点数,后缀的和,后缀的平方和
    ELE(LL tq = 0, LL ts1 = 0, LL ts2 = 0): qua(tq), suf1(ts1), suf2(ts2)
    {}
};


ELE table[25][7][7][2];
bool vis[25][7][7][2];
LL pow10[25];
int digit[25];

ELE dfs(int len, int st1, int st2, int flag, bool bound)
{
    if(len == 0)
        if(st1 != 0 && st2 != 0 && flag == 0)
            return ELE(1, 0, 0);
        else
            return ELE(0, 0, 0);
    if(!bound && vis[len][st1][st2][flag])
        return table[len][st1][st2][flag];
    ELE ret, ret2;
    int up = bound? digit[len]: 9;
    for(int i = 0; i <= up; ++i)
    {
        ret2 = dfs(len-1, (st1+i)%7, (st2*10+i)%7, flag|(i == 7? 1: 0), bound && i == up);
        ret.qua = (ret.qua+ret2.qua)%MOD;
        LL temp = i*pow10[len-1]%MOD;
        ret.suf1 = (temp*ret2.qua%MOD+ret2.suf1+ret.suf1)%MOD;  //利用性质进行转移 
        ret.suf2 = ( temp*temp%MOD*ret2.qua%MOD
                    +ret2.suf2+temp*ret2.suf1%MOD*2+ret.suf2)%MOD;                     
    }
    if(!bound)
    {
        vis[len][st1][st2][flag] = true;
        table[len][st1][st2][flag] = ret;
    }
    return ret;
}

LL fun(LL num)
{
    int len = 1;
    while(true)
    {
        digit[len] = num%10;
        num /= 10;
        if(num == 0)
            break;
        ++len;
    }
    ELE ret = dfs(len, 0, 0, 0, true);
    return ret.suf2;
}

int main()
{
    memset(vis, 0, sizeof(vis));
    pow10[0] = 1;
    for(int i = 1; i <= 19; ++i)
        pow10[i] = pow10[i-1]*10;
    int TC;
    scanf("%d", &TC);
    while(TC--)
    {
        LL a, b;
        scanf("%I64d%I64d", &a, &b);
        printf("%I64d\n", (fun(b)-fun(a-1)+MOD)%MOD);
    }
    return 0;
}
 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值