您的位置:首页 > 其它

hdu 4507 吉哥系列故事——恨7不成妻 数位DP

2013-04-28 20:34 363 查看
中文题

做法:奇葩,要求区间中数字的平方和。sigma(a1,a2... an) = n*sigma(first)*sigma(first) + 2*sigma(first)*sigma(he) + sigma(squre);

a1,..a2...an代表区间中的每个数, first 代表他们共用的首位*10^(i - 1),i是这个数的位数,squre 代表平方和, he 代表其他位数组成数字的和。

#include <cstdio>
#include <cstring>
typedef __int64 LL;
const int mod = 1000000000 + 7;
const int LMT = 7;
const int LEN = 20;
//一开始的取膜方法写错了,重复不同数的取膜最后答案会错误
//为了保险,能取模就取模
LL _squre[7][7][LEN], _sum[7][7][LEN],ten[LEN], have[7][7][LEN];
int num[LEN];
void init(void)
{
   memset(_squre, -1, sizeof(_squre));
   memset(_sum, -1, sizeof(_sum));
   memset(have, -1, sizeof(have));
}
struct __ret
{
    LL sq, sm, hv;
    __ret(LL a, LL b, LL c): sq(a), sm(b), hv(c) {}
    __ret():sq(0), sm(0), hv(0){}
};
__ret dfs(const int &now, const int &rest, const int &sum, const bool &tag)
{
    if(rest == 0) 
    {
        if (now && sum) return __ret(0, 0, 1);
        else return __ret(-1, -1, 0);
    }
    if (!tag && _squre[now][sum][rest] != -1)
        return __ret(_squre[now][sum][rest], _sum[now][sum][rest], have[now][sum][rest]);
    int i,end = (tag ? num[rest] : 9);
    __ret tem;
    LL sqr = 0, sm = 0, hv = 0, prep;
    for(i = 0; i <= end; ++i)
    if(i != 7)
    {
            prep = i * ten[rest - 1] % mod;
            tem = dfs((now*10 + i)% 7, rest - 1, (sum + i) % 7, tag && (i == end));
            if(tem.sq != -1)
            {
              sqr += (prep * prep % mod * tem.hv % mod + 2 * tem.sm * prep %mod  + tem.sq) % mod;
              sqr %= mod;
              sm += (tem.hv%mod*prep % mod + tem.sm) % mod;
              sm %= mod;
              hv += tem.hv;
              hv %= mod;
            }
    }
    if(!tag)//这里又错了return了数组值,哭...
    {
        _squre[now][sum][rest] = sqr;
        _sum[now][sum][rest] = sm;
        have[now][sum][rest] = hv;
    }
    return __ret(sqr, sm, hv);
}
int get_num(LL x)
{
    int res = 0;
    do
      num[++res] = int(x % 10);
    while(x /= 10);
    return res;
}
int main(void)
{
    init();
    int T,lena,lenb;
    LL a,b,resa,resb, ans;
    init();
    ten[0] = 1;
    for(int i = 1; i <= 18; ++i)
        ten[i] = (ten[i - 1] * 10) % mod;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%I64d%I64d",&a, &b);
        if(a > b)
        {
            a = a ^ b;
            b = a ^ b;
            a = a ^ b;
        }
        a--;
        lena = get_num(a);
        resa = dfs(0, lena, 0, 1).sq;
        lenb = get_num(b);
        resb = dfs(0, lenb, 0, 1).sq;
        ans = resb - resa;
        if(ans < 0) ans = ans + mod;
        printf("%I64d\n", ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: