您的位置:首页 > 其它

hdu4507——数位dp

2013-08-13 16:57 218 查看
题意:计算给定区间内,不整除7、不含有7、数位之和不整除7的所有数的平方和。

思路和普通的数位dp一致,就是求平方和有点恶心。得求出每个状态的三个值:满足该状态的数的个数,这些数的和,这些数的平方和。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define lng long long
using namespace std;

const int mod = 1000000007;
struct pp
{
lng ans1, ans2, ans3;
int vis;
}dp[2][19][10][10];
int num[19], tot;
lng a, b;
lng fac[40];

void dfs(int pos, int pre1, int pre2, int ok)
{
if(dp[ok][pos][pre1][pre2].vis) return;
pp & ans = dp[ok][pos][pre1][pre2];
ans.vis = 1;
if(pos == 0)
{
int end = ok ? num[pos] : 9;
for(int i = 0; i <= end; ++i)
{
if(i == 7) continue;
if((pre1 + i) % 7 != 0 && (pre2 * 10 + i) % 7 != 0) { ans.ans1++; ans.ans2 += i; ans.ans3 += i * i; }
}
}
else
{
int end = ok ? num[pos] : 9;
for(int i = 0; i <= end; ++i)
{
if(i == 7) continue;
int x1 = (pre1 + i) % 7, x2 = (pre2 * 10 + i) % 7, x3 = (ok && i == end);
dfs(pos - 1, x1, x2, x3);
pp & tans = dp[x3][pos - 1][x1][x2];
ans.ans1 += tans.ans1;
ans.ans1 %= mod;
ans.ans2 += (((i * fac[pos]) % mod) * tans.ans1) % mod + tans.ans2;
ans.ans2 %= mod;
lng tmp = ((i * i) * fac[2 * pos]) % mod;
ans.ans3 += ((tmp * tans.ans1) % mod);
ans.ans3 += tans.ans3;
ans.ans3 += (((2 * i * fac[pos]) % mod) * tans.ans2) % mod;
ans.ans3 %= mod;
}
}
}

lng calc(lng n)
{
if(n == 0) return 0;
tot = 0;
while(n) { num[tot++] = n % 10; n /= 10; }
memset(dp[1], 0, sizeof(dp[1]));
dfs(tot - 1, 0, 0, 1);
return dp[1][tot - 1][0][0].ans3;
}

void prework()
{
cin >> a >> b;
}

void solve()
{
lng ans = calc(b) - calc(a - 1);
ans %= mod;
if(ans < 0) ans += mod;
cout << ans << "\n";
}

int main()
{
memset(dp, 0, sizeof(dp));
fac[0] = 1;
for(int i = 1; i < 40; ++i) fac[i] = (fac[i - 1] * 10) % mod;
int t; cin >> t;
while(t--)
{
prework();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: