HDU - 4507 吉哥系列故事——恨7不成妻(数位dp)
题目链接:点击查看
题目大意:给出闭区间[l,r],求出区间内与7不沾边的数的平方和
与7有关的条件:
- 整数中某一位是7;
- 整数的每一位加起来的和是7的整数倍;
- 这个整数是7的整数倍;
题目分析:抛去平方和,如果改成统计有多少个符合条件的数字,那就是传统的数位dp了,只需维护一个dp[pos][sum1][sum2]即可,pos表示位数,sum1表示第二个条件的余数,sum2表示第三个条件的余数,向下传递的时候按照规则模拟即可,如果不懂的话看一眼代码就好了
下面重点讲一下如何处理平方和,关于维护数位dp中的平方和,我看到网上一个很巧妙的方法,需要维护三个值,分别是符合条件的数量,截止到当前位的符合条件的数值总和,截止到当前位的符合条件的平方和,为了方便传递,这里用一个结构体封装一下。
那么下面先介绍参数变量,数量用cnt表示,总和用sum表示,平方和用powsum表示,然后按照传统数位dp的思想,我们需要用到回溯法,从最高位先下传到最低位然后回溯,随后自底向上不断传递状态,那么我们可以假设两个结构体:ans和temp,ans表示当前递归函数正在处理的数据,temp表示已经从底部返回上来的数据,即已经处理完成的数据,返回到ans中进一步处理。
如果不太理解ans和temp的关系,我再进一步说明一下,举个例子,ans正在处理当前数位从0~9的数字,每个数字下传后返回上来的结果,那么temp就表示每个数字下传返回上来的结果,也就是说ans比temp高一级。
大概是这个样子的一个关系
然后就是需要处理cnt,sum和powsum这三个参数该如何传递了
关于cnt,就是最基础的数位dp的传递思路,只需要不断累加就行,这里不过赘述,直接写出转移方程:
ans.cnt+=temp.cnt;
关于sum,我们首先可以先将当前表示的数字重构一下,表示为,i表示为最高位,x表示为剩余的低位部分,不过这只是表示的一个符合条件的数的sum,我们目前一共有cnt个数符合条件,所以这个结果需要乘以cnt,那么就显而易见了,x就相当于已经处理完的上一级返回的sum的值了,想一想是不是?为了表示方便,我们用一个辅助数组p,来存储每一位的进制,即p[1]=1,p[2]=10,p[3]=100以此类推,这样就可以表示为
ans.sum+=(i*p[pos]+x)*temp.cnt;
化简一下:
ans.sum+=i*p[pos]*temp.cnt+temp.sum;
还剩下一个平方和,这个的话需要在纸上化简一下,是个完全平方公式,接着上面的重构的数字来说,平方和就是求这个结果,但直接求肯定不好求,需要化简一下,展开平方后为:最后别忘了整体乘上cnt就好,那么初始的公式为:
ans.powsum+=(i*i*p[pos]*p[pos]+x*x+2*i*p[pos]*x)*temp.cnt;
把temp.cnt乘进去消掉x:
ans.powsum+=i*i*p[pos]*p[pos]*temp.cnt+temp.powsum+2*i*p[pos]*temp.sum;
这样转移方程就都有了,再说一下为什么temp.cnt与x相遇可以消去吧,因为我们一开始也提到了,temp.sum和temp.powsum指的是从temp中传递上来的结果,就是已经计算完毕的结果,已经乘过cnt了,而x表示的是上一层中关于一个可行数字的总和和平方和,所以这一层的x遇到cnt就可以用上一层的sum和powsum来替换了。
还有一点需要注意,在计算的过程中要实时取模,代码中的具体实现是上述转移方程穿插了无数个mod后的成品,及其难看,所以不用过多在意美观性了。。在计算过程中cnt,sum和powsum都会爆int,所以记得开long long,最后就是输出结果的时候,因为取模的原因,可能solve(b)比solve(a-1)要小,所以记得对负数取模:
(solve(b)-solve(a-1)+mod)%mod
上代码了:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=(1<<21)+100;struct Node
{LL cnt,sum,powsum;//符合条件的个数,截止到目前为止的总和,截止到目前为止的平方和Node(){cnt=sum=powsum=0;}
}dp[20][7][7];//dp[pos][sum%mod][mod]LL b[20];LL p[20];const int mod=1e9+7;Node dfs(int pos,int sum,int sum2,bool limit)
{if(pos==0){Node temp;if(sum%7==0||sum2%7==0)temp.cnt=0;elsetemp.cnt=1;return temp;}if(!limit&&dp[pos][sum][sum2].cnt!=-1)return dp[pos][sum][sum2];int up=limit?b[pos]:9;Node ans;for(int i=0;i<=up;i++){if(i==7)continue;Node temp=dfs(pos-1,(sum+i)%7,(sum2*10+i)%7,limit&&i==b[pos]);ans.cnt=(ans.cnt+temp.cnt)%mod;ans.sum=(ans.sum+(p[pos]*i%mod*temp.cnt%mod)+temp.sum)%mod;ans.powsum=(ans.powsum+i*i*p[pos]%mod*p[pos]%mod*temp.cnt%mod+temp.powsum+2*i*p[pos]%mod*temp.sum%mod)%mod;}if(!limit)dp[pos][sum][sum2]=ans;return ans;
}LL solve(LL n)
{int cnt=0;while(n){b[++cnt]=n%10;n/=10;}return dfs(cnt,0,0,true).powsum;
}int main()
{
// freopen("input.txt","r",stdin);int w;cin>>w;memset(dp,-1,sizeof(dp));p[1]=1;for(int i=2;i<20;i++)p[i]=p[i-1]*10%mod;while(w--){LL a,b;cin>>a>>b;cout<<(solve(b)-solve(a-1)+mod)%mod<<endl;}return 0;
}
HDU - 4507 吉哥系列故事——恨7不成妻(数位dp)相关推荐
- HDU 4507 吉哥系列故事――恨7不成妻 数位DP
吉哥系列故事--恨7不成妻 Time Limit: 1000/500 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- HDU-4507 吉哥系列故事――恨7不成妻 (数位dp)
J - 吉哥系列故事――恨7不成妻 HDU - 4507 题解:数位dp 和简单的数位dp不同,这道题要算所有合法数的平方和 考虑到一个数可以写成X=ΣAi*Pi,(其中Ai为X每一位的值,Pi=10 ...
- HDU 4507 吉哥系列故事——恨7不成妻 详解(变态数位DP)
Problem Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: ...
- HDU - 4507 吉哥系列故事――恨7不成妻 (数位DP)
Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: 2+1+4=7 ...
- HDU 4507 吉哥系列故事――恨7不成妻 (平方拆解 + *数位DP 总结)
单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: 2+1+4=7 7+7 ...
- hdu4507吉哥系列故事——恨7不成妻 (数位dp)
Problem Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: ...
- HDU 4507 吉哥系列故事——恨7不成妻(数位DP)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove Tencent马拉松初赛第二场的鬼畜题... 其实 ...
- HDU4507 吉哥系列故事――恨7不成妻 数位DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4507 题意:求[L,R](1 <= L <= R <= 10^18)区间内和7无关的 ...
- 吉哥系列故事——恨7不成妻(数位 DP)
吉哥系列故事--恨7不成妻 ∑i=1n(pre+suc)2∑i=1npre2+suc2+2×pre×sucn×pre2+∑suc2+2×pre∑suc\sum_{i = 1} ^{n}(pre + s ...
最新文章
- python能做表格吗-python 制作表格
- Oracle四舍五入,向上取整,向下取整
- 华为云查询弹性云服务器规格信息,通用计算型弹性云服务器规格介绍详情-华为云...
- MFC多文档应用程序同时显示两个视图
- 基于 jQuery支持移动触摸设备的Lightbox插件
- no [query] registered for [filtered] in es7 的解决方法
- 【干货】华为企业数字化转型之道.pdf(附下载链接)
- deploy mysql_Deploy Mysql
- 女生长胖是一种什么样的体验?
- Linux多进程编程(1)
- Ubuntu18.04安装wireshark3.0.6(版本可自己选)
- 位图和矢量图区别,PS和AI的区别
- C语言中 1%3,算术什么意思啊 算数什么意思
- 纺织服装产业实现智能制造升级
- 从面试官的角度谈谈后端面试
- 3ds Max 材质贴图
- 云计算的优势和存在的问题
- 程序员经常看的开源月刊《HelloGitHub》第 56 期
- python qq群自动加入_Python实现向QQ群成员自动发邮件的方法
- 机器学习之神经网络图解,生动形象