HDU4507吉哥系列故事——恨7不成妻(数位dp)
来源:互联网 发布:试用源码 编辑:程序博客网 时间:2024/05/17 18:03
关于状态转移,先简单的写这样一个式子:dp[i][j][k] = ∑dp[i-1][(j+dig)%7][(k*10+dig)%7](这里的求和符号不指加法,是一个抽象的意义)
其中dig是枚举的正在处理的数位i上所有可能的数字(这个式子只能帮助理解状态是如何转移的但是却不表示具体的运算,dp是结构体当然不能直接运算)
上面的等式,我们称等式左边表示总状态,等式右边为其子状态,显然总状态是等于所有子状态的“总和”(我说的状态的总和并非指加法运算)
那么怎么通过子状态算出总状态呢?
具体的计算:
先说几句废话:
对于13这个数,它的数位上的数是1,3,它的数位和是1+3,它自身的数值是 1*10+3
如果我知道数字13是与7无关的数,在其前面加一个1,也是与7无关的数,怎样计算在其前面加一个1之后的数的平方和的呢
(1*100)^2 + 2*(1*100)*13 + 13^2 这里相当于(100+13)^2
注意:在具体的状态转移中,我们是不知道13这个值,我们只知道有这么一个子状态
要求的是所有满足的数的平方和,所以最后具体的算式如下:
设总状态(当前状态)为ret,它其中一个子状态为nxt,枚举正在处理的这一数位上的数字为 i ,数位 i 在整个数字中具体的数值是i*10^pw10[pos]
那么有:
(1) ret.cnt += ret.cntnxt.cnt//这个与求个数的那类题型一样
(2) ret.sum += nxt.sum + i*10^pw10[pos]*nxt.cnt //之所以*数量,是因为后面有许多个符合条件的数,这一位可以跟后面所有符合条件的数搭配
(3) ret.sqsum += nxt.sqsum + 2*(i*10^pw10[pos])*nxt.sum + [(i*10^pw10[pos])^2]*nxt.cnt//这个是最难理解的式子,也就是是上面的完全平方式子,因为当前位固定,后面有很多满足情况的数位,所以与单独一个1配上后面13有点不一样,此处需要理解10分钟
#include<iostream>#include<cstring>#include<cstdio>using namespace std;typedef long long ll;const ll mod = (ll)(1e9+7);int digit[20], vis[20][10][10];ll pw10[20];struct Node{ ll cnt, sum, sqsum; Node(){cnt = -1; sum = 0; sqsum = 0;} Node(ll _cnt, ll _sum, ll _sqsum): cnt(_cnt), sum(_sum), sqsum(_sqsum){}}dp[20][10][10];Node dfs(int pos, int sum_rem, int num_rem, bool limit){ if(pos == -1) { if(sum_rem == 0 || num_rem == 0) return Node{0, 0 , 0}; else return Node{1, 0, 0}; } if(!limit && dp[pos][sum_rem][num_rem].cnt != -1) return dp[pos][sum_rem][num_rem]; int last = limit ? digit[pos] : 9; Node ret = Node{0, 0, 0}; for(int i = 0; i <= last; i++) { if(i == 7) continue; Node nxt = dfs(pos - 1, (sum_rem + i) % 7, (num_rem * 10 + i) % 7, limit && (i == last)); ret.cnt = (ret.cnt + nxt.cnt) % mod; ret.sum = ((ret.sum + pw10[pos] * i % mod * nxt.cnt % mod) % mod + nxt.sum) % mod; ret.sqsum = (ret.sqsum + nxt.sqsum) % mod; ret.sqsum = (ret.sqsum + pw10[pos] * pw10[pos] % mod * i * i % mod * nxt.cnt % mod) % mod; ret.sqsum = (ret.sqsum + 2 * pw10[pos] * i % mod * nxt.sum % mod) % mod; } if(!limit) dp[pos][sum_rem][num_rem] = ret; return ret;}ll solve(ll x){ memset(digit, 0, sizeof(digit)); int len = 0; while(x) { digit[len++] = x % 10; x /= 10; } return dfs(len-1, 0, 0, true).sqsum;}int main(){ int T; ll L, R; pw10[0] = 1; for(int i = 1; i <= 18; i++) pw10[i] = pw10[i-1] * 10 % mod; scanf("%d", &T); while(T--) { scanf("%I64d%I64d", &L, &R); ll ans = (solve(R) - solve(L-1)) % mod; printf("%I64d\n", (ans + mod) % mod); } return 0;}
- hdu4507 吉哥系列故事——恨7不成妻 数位DP
- hdu4507吉哥系列故事——恨7不成妻 数位dp
- 【HDU4507】【吉哥系列故事——恨7不成妻】【变形数位dp】
- hdu4507吉哥系列故事——恨7不成妻 (数位dp)
- HDU4507吉哥系列故事——恨7不成妻(数位dp)
- [数位DP] HDU4507 吉哥系列故事——恨7不成妻
- 【数位DP】HDU4507[吉哥系列故事——恨7不成妻]题解
- HDU4507 吉哥系列故事――恨7不成妻 数位DP
- 吉哥系列故事——恨7不成妻 hdu4507
- hdu4507 吉哥系列故事——恨7不成妻
- HDU4507 吉哥系列故事——恨7不成妻
- [数位DP]HDU 4507——吉哥系列故事——恨7不成妻
- HDU 4507 吉哥系列故事——恨7不成妻(数位DP)
- hdu 4507 吉哥系列故事——恨7不成妻 数位DP
- hdu 4507 吉哥系列故事——恨7不成妻(数位DP,5级)
- HDU 4507 吉哥系列故事——恨7不成妻(数位DP)
- hdu 吉哥系列故事——恨7不成妻 数位DP
- 【数位DP】HDU 4507 吉哥系列故事——恨7不成妻
- Canvas开篇之drawBitmap方法讲解
- Robotframework 入门教程(一)
- CodeForces-124A-The number of positions
- 安卓中菜单的使用
- 吾爱破解专用虚拟机系统不能安装VMwaretools问题!
- HDU4507吉哥系列故事——恨7不成妻(数位dp)
- Android手机一键Root原理分析
- 3.1入门模拟B1016.部分A+B
- 在C/C++中嵌入python, 用PyImport_ImportModule返回值总是为0的解决方法
- Canvas进阶之translate、scale、rotate、skew方法讲解!
- iOS开发私有变量和私有方法
- 【Android View绘制之旅】主脉络
- i2c 协议解析
- Spring_12_通过 FactoryBean 配置 Bean