HDU 4507 恨7不成妻 (数位DP套路题,详细解析)

2023-10-10 12:59

本文主要是介绍HDU 4507 恨7不成妻 (数位DP套路题,详细解析),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

不会数位 D P DP DP的这里指路一篇介绍非常详细的数位 D P DP DP b l o g blog blog:点这里。

  • 链接
    恨7不成妻

  • 题面

    单身!
    依然单身!
    吉哥依然单身!
    DS级码农吉哥依然单身!
    所以,他生平最恨情人节,不管是214还是77,他都讨厌!
    吉哥观察了214和77这两个数,发现:
    2 + 1 + 4 = 7 2+1+4=7 2+1+4=7 
    7 + 7 = 7 ∗ 2 7+7=7*2 7+7=72
    77 = 7 ∗ 11 77=7*11 77=711
    最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数!什么样的数和7有关呢?如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——
       1、整数中某一位是7;
       2、整数的每一位加起来的和是7的整数倍;
       3、这个整数是7的整数倍;

    现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
     Input
     输入数据的第一行是case数T(1 <= T <= 50),然后接下来的T行表示T个case;每个case在一行内包含两个正整数L, R(1 <= L <= R <= 10^18)。
     Output
     请计算[L,R]中和7无关的数字的平方和,并将结果对10^9 + 7 求模后输出。
     Sample Input

    3
    1 9
    10 11
    17 17
    

    Sample Output

    236
    221
    0
    
  • 解题思路

    根据题意我们做出预处理,利用闫式 D P DP DP分析法分析如下:

以上只是简单分析,我们还并没有真正的进行状态转移和计算,那么根据题意,首先是需要知道整数的每一位加起来的和是 7 7 7的整数倍以及该整数是 7 7 7的整数倍,这个好处理,在我们的前面的题中有类似的题型,这已经在我们的 f f f数组的第三维和第四维了。所以难点就在于怎么处理整数的平方和。我们看下面的公式推导:

我们用 j A jA jA来表示 i i i位数,而其中的 A A A i − 1 i-1 i1位数。设这个状态有 t t t个符合要求的数,分别是 A 1 A_1 A1~ A t A_t At 那么,平方和易得为:

( j A 1 ) 2 + ( j A 2 ) 2 + ( j A 3 ) 2 + . . . + ( j A t − 1 ) 2 + ( j A t ) 2 (jA_1)^2+(jA_2)^2+(jA_3)^2+...+(jA_{t-1})^2+(jA_t)^2 (jA1)2+(jA2)2+(jA3)2+...+(jAt1)2+(jAt)2

(我们分割表示将 A A A提取出来。)

= ( j ∗ 1 0 i − 1 + A 1 ) 2 + ( j ∗ 1 0 i − 1 + A 2 ) 2 + ( j ∗ 1 0 i − 1 + A 3 ) 2 + . . . + ( j ∗ 1 0 i − 1 + A t − 1 ) 2 + ( j ∗ 1 0 i − 1 + A t ) 2 =(j*10^{i-1}+A_1)^2+(j*10^{i-1}+A_2)^2+(j*10^{i-1}+A_3)^2+...+(j*10^{i-1}+A_{t-1})^2+(j*10^{i-1}+A_t)^2 =(j10i1+A1)2+(j10i1+A2)2+(j10i1+A3)2+...+(j10i1+At1)2+(j10i1+At)2

(平方和公式)

= t ∗ ( j ∗ 1 0 i − 1 ) 2 + 2 ∗ ( j ∗ 1 0 i − 1 ) ∗ ( A 1 + . . . + A t ) + ( A 1 2 + . . . + A 2 ) =t*(j*10^{i-1})^2+2*(j*10^{i-1})*(A_1+...+A_t)+(A_1^2+...+A^2) =t(j10i1)2+2(j10i1)(A1+...+At)+(A12+...+A2)

这样,在这个式子中,由于 j j j已知,所以我们发现 f f f数组需要保存三个值。 A A A 0 0 0次方之和,也就是符合要求的数, A A A 1 1 1次方之和,也就是符合要求的除去 j j j i − 1 i-1 i1位数相加, A A A 2 2 2次方之和,也就是符合要求的除去 j j j i − 1 i-1 i1位数平方相加。我们分别用 s 0 , s 1 , s 2 s_0,s_1,s_2 s0,s1,s2

分别代表上述的三个值。

那么这里我们需要怎么求 s 1 s_1 s1,如下:

注:这里的 s 1 s_1 s1 i + 1 i+1 i+1位的 s 1 s_1 s1,而它存储的就是 i i i位的 A A A

j A 1 + . . . + j A t jA_1+...+jA_t jA1+...+jAt

= j ∗ 1 0 i − 1 + ( A 1 + . . . + A t ) =j*10^{i-1}+(A_1+...+A_t) =j10i1+(A1+...+At)

所以我们的 f f f应该是一个结构体数组,它需要存取 s 0 , s 1 , s 2 s_0,s_1,s_2 s0,s1,s2。那么预处理根据上述分析其实就简单了。那么就按照数位 D P DP DP的套路解决这道题即可。需要注意这道题好多坑点,多取模,足够细心才可以解决。(调 B u g Bug Bug调了好久。快绝望了。)

  • 代码
/***@filename:恨7不成妻*@author: pursuit*@csdn:unique_pursuit*@email: 2825841950@qq.com*@created: 2021-05-12 21:19
**/
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int N = 20;
const ll P = 1e9+7;//需要满足三个性质。
//1.不含7.
//2.各位数字之和模7不为0.an-1+...+a0%7!=0. 
//3.该数模7不为0.an-1*pow(10,n-1)+...+a0+pow(10,0)%7!=0struct F{ll s0,s1,s2;//s0为符合要求的数。s1为符合要求的数1次方之和,s2为符合要求的数的2次方之和。
}f[N][10][7][7];//f[i][j][k][u]表示总共有i位数且最高位是j,该数值模7为k,各位数数字之和模7为u的所有数的s0,s1,s2.
//进行初始化。
int t;//测试数。
ll l,r;
ll power7[N],power9[N];//power7[i]存储10^i余7的余数,power9[i]存储10^i余P的余数。
ll mod(ll x,ll y){return (x%y+y)%y;
}
void init(){//确定初始值,位数为1的情况。for(int j=0;j<10;j++){if(j==7)continue;//根据性质排除不符合要求的。F &v=f[1][j][j%7][j%7];//这里用引用减少代码量。v.s0++;v.s1+=j;v.s2+=j*j;}ll power = 10;//辅助作用,表示10的i-1次方。for(int i=2;i<N;i++,power*=10){for(int j=0;j<10;j++){if(j==7)continue;//排除不符合要求的数。for(int k=0;k<7;k++){for(int u=0;u<7;u++){for(int q=0;q<10;q++){//枚举i-1的最高位。if(q==7)continue;F &x=f[i][j][k][u],y=f[i-1][q][mod(k-j*(power%7),7)][mod(u-j,7)];//s0,s1,s2都是通过公式就算得到。x.s0=mod(x.s0+y.s0,P);x.s1=mod(x.s1+1LL*j%P*(power%P)%P*y.s0%P+y.s1,P);x.s2=mod(x.s2+1LL*j%P*y.s0%P*(power%P)%P*j%P*(power%P)%P+1LL*y.s1%P*2%P*j%P*(power%P)%P+y.s2,P);}}}}}//这里处理为了方便以及降低时间复杂度。power7[0]=1,power9[0]=1;for(int i=1;i<N;i++){power7[i]=power7[i-1]*10%7;power9[i]=power9[i-1]*10%P;}
}
F get(int i,int j,int k,int u){//因为f[i][j][k][u]是本身模7等于k,且各位数之和模7等于u的,所以我们需要找出符合条件的集合。ll s0=0,s1=0,s2=0;for(int x=0;x<7;x++){for(int y=0;y<7;y++){if(x==k||y==u)continue;F v=f[i][j][x][y];s0=mod(s0+v.s0,P);s1=mod(s1+v.s1,P);s2=mod(s2+v.s2,P);}}return {s0,s1,s2};
}
ll dp(ll n){if(!n)return 0;//0的平方和为0.vector<int> a;ll temp=n%P;//备份一个n,供后面判断n使用。while(n)a.push_back(n%10),n/=10;ll last_a=0,last_b=0;//这里我们需要存储前缀的本身值和前缀的个位数之和。ll ans=0;//答案。for(int i=a.size()-1;i>=0;i--){int x=a[i];for(int j=0;j<x;j++){//走左分支。if(j==7)continue;//我们需要将符合条件的数筛出来,这里要用到一个get函数。//求得本身模7不等于a,并且各位数之和模7不等b的集合,此时就可以使用预处理出来的结构体int k=mod(-last_a*power7[i+1],7),u=mod(-last_b,7);F v=get(i+1,j,k,u);//cout<<v.s0<<" "<<v.s1<<" "<<v.s2<<endl;//根据公式求解s2.//j就是last_a.ans=mod(ans+1LL*(last_a%P)*(last_a%P)%P*(power9[i+1]%P)%P*(power9[i+1]%P)%P*v.s0%P+1LL*2*last_a%P*(power9[i+1]%P)%P*v.s1%P+v.s2,P);//cout<<ans<<endl;}//判断x。if(x==7)break;//走右分支更新。last_a=last_a*10+x;last_b+=x;//判断自己本身是否符合要求。if(!i&&last_a%7&&last_b%7){ans=mod(ans+temp*temp%P,P);}}return ans;
}
int main(){init();cin>>t;while(t--){cin>>l>>r;cout<<mod(dp(r)-dp(l-1),P)<<endl;}return 0;
}
/*
1
1 1000000000000000000
*/

这篇关于HDU 4507 恨7不成妻 (数位DP套路题,详细解析)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/180601

相关文章

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

关于WebSocket协议状态码解析

《关于WebSocket协议状态码解析》:本文主要介绍关于WebSocket协议状态码的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录WebSocket协议状态码解析1. 引言2. WebSocket协议状态码概述3. WebSocket协议状态码详解3

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

Ubuntu中远程连接Mysql数据库的详细图文教程

《Ubuntu中远程连接Mysql数据库的详细图文教程》Ubuntu是一个以桌面应用为主的Linux发行版操作系统,这篇文章主要为大家详细介绍了Ubuntu中远程连接Mysql数据库的详细图文教程,有... 目录1、版本2、检查有没有mysql2.1 查询是否安装了Mysql包2.2 查看Mysql版本2.

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

Win11安装PostgreSQL数据库的两种方式详细步骤

《Win11安装PostgreSQL数据库的两种方式详细步骤》PostgreSQL是备受业界青睐的关系型数据库,尤其是在地理空间和移动领域,:本文主要介绍Win11安装PostgreSQL数据库的... 目录一、exe文件安装 (推荐)下载安装包1. 选择操作系统2. 跳转到EDB(PostgreSQL 的

Python3.6连接MySQL的详细步骤

《Python3.6连接MySQL的详细步骤》在现代Web开发和数据处理中,Python与数据库的交互是必不可少的一部分,MySQL作为最流行的开源关系型数据库管理系统之一,与Python的结合可以实... 目录环境准备安装python 3.6安装mysql安装pymysql库连接到MySQL建立连接执行S

将Mybatis升级为Mybatis-Plus的详细过程

《将Mybatis升级为Mybatis-Plus的详细过程》本文详细介绍了在若依管理系统(v3.8.8)中将MyBatis升级为MyBatis-Plus的过程,旨在提升开发效率,通过本文,开发者可实现... 目录说明流程增加依赖修改配置文件注释掉MyBATisConfig里面的Bean代码生成使用IDEA生