题目链接:点击查看

题目大意:给出闭区间[l,r],求出区间内与7不沾边的数的平方和

与7有关的条件:

  1. 整数中某一位是7;
  2. 整数的每一位加起来的和是7的整数倍;
  3. 这个整数是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)相关推荐

  1. HDU 4507 吉哥系列故事――恨7不成妻 数位DP

    吉哥系列故事--恨7不成妻 Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  2. HDU-4507 吉哥系列故事――恨7不成妻 (数位dp)

    J - 吉哥系列故事――恨7不成妻 HDU - 4507 题解:数位dp 和简单的数位dp不同,这道题要算所有合法数的平方和 考虑到一个数可以写成X=ΣAi*Pi,(其中Ai为X每一位的值,Pi=10 ...

  3. HDU 4507 吉哥系列故事——恨7不成妻 详解(变态数位DP)

    Problem Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: ...

  4. HDU - 4507 吉哥系列故事――恨7不成妻 (数位DP)

    Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: 2+1+4=7 ...

  5. HDU 4507 吉哥系列故事――恨7不成妻 (平方拆解 + *数位DP 总结)

    单身!  依然单身!  吉哥依然单身!  DS级码农吉哥依然单身!  所以,他生平最恨情人节,不管是214还是77,他都讨厌!    吉哥观察了214和77这两个数,发现:  2+1+4=7  7+7 ...

  6. hdu4507吉哥系列故事——恨7不成妻 (数位dp)

    Problem Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: ...

  7. HDU 4507 吉哥系列故事——恨7不成妻(数位DP)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove Tencent马拉松初赛第二场的鬼畜题... 其实 ...

  8. HDU4507 吉哥系列故事――恨7不成妻 数位DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4507 题意:求[L,R](1 <= L <= R <= 10^18)区间内和7无关的 ...

  9. 吉哥系列故事——恨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 ...

最新文章

  1. python能做表格吗-python 制作表格
  2. Oracle四舍五入,向上取整,向下取整
  3. 华为云查询弹性云服务器规格信息,通用计算型弹性云服务器规格介绍详情-华为云...
  4. MFC多文档应用程序同时显示两个视图
  5. 基于 jQuery支持移动触摸设备的Lightbox插件
  6. no [query] registered for [filtered] in es7 的解决方法
  7. 【干货】华为企业数字化转型之道.pdf(附下载链接)
  8. deploy mysql_Deploy Mysql
  9. 女生长胖是一种什么样的体验?
  10. Linux多进程编程(1)
  11. Ubuntu18.04安装wireshark3.0.6(版本可自己选)
  12. 位图和矢量图区别,PS和AI的区别
  13. C语言中 1%3,算术什么意思啊 算数什么意思
  14. 纺织服装产业实现智能制造升级
  15. 从面试官的角度谈谈后端面试
  16. 3ds Max 材质贴图
  17. 云计算的优势和存在的问题
  18. 程序员经常看的开源月刊《HelloGitHub》第 56 期
  19. python qq群自动加入_Python实现向QQ群成员自动发邮件的方法
  20. 机器学习之神经网络图解,生动形象

热门文章

  1. 线程回顾Thread
  2. Dubbo对于REST协议的支持
  3. Spring提供获取应用上下文的工具
  4. 日志规范之slf4j整合Log4j以及Logback
  5. 使用springaop技术面向切面编程
  6. 设计模式------代理模式
  7. oracle 分析函数、GROUPING函数
  8. python字典有什么用_在Python中使用范围作为字典键,我有什么选...
  9. 安装mysql 没有快捷_快速安装mysql
  10. d3中文案例_D3.js柱状图例子