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

相关文章

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

Spring boot整合dubbo+zookeeper的详细过程

《Springboot整合dubbo+zookeeper的详细过程》本文讲解SpringBoot整合Dubbo与Zookeeper实现API、Provider、Consumer模式,包含依赖配置、... 目录Spring boot整合dubbo+zookeeper1.创建父工程2.父工程引入依赖3.创建ap

MyBatis中$与#的区别解析

《MyBatis中$与#的区别解析》文章浏览阅读314次,点赞4次,收藏6次。MyBatis使用#{}作为参数占位符时,会创建预处理语句(PreparedStatement),并将参数值作为预处理语句... 目录一、介绍二、sql注入风险实例一、介绍#(井号):MyBATis使用#{}作为参数占位符时,会

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

创建Java keystore文件的完整指南及详细步骤

《创建Javakeystore文件的完整指南及详细步骤》本文详解Java中keystore的创建与配置,涵盖私钥管理、自签名与CA证书生成、SSL/TLS应用,强调安全存储及验证机制,确保通信加密和... 目录1. 秘密键(私钥)的理解与管理私钥的定义与重要性私钥的管理策略私钥的生成与存储2. 证书的创建与

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

Python设置Cookie永不超时的详细指南

《Python设置Cookie永不超时的详细指南》Cookie是一种存储在用户浏览器中的小型数据片段,用于记录用户的登录状态、偏好设置等信息,下面小编就来和大家详细讲讲Python如何设置Cookie... 目录一、Cookie的作用与重要性二、Cookie过期的原因三、实现Cookie永不超时的方法(一)

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1