【HDU4507】恨7不成妻(数位DP)
大致题意: 让你求出一段区间内与\(7\)无关的数的平方和。与\(7\)无关的数指整数中任意一位不为\(7\)、整数的每一位加起来的和不是\(7\)的整数倍、这个整数不是\(7\)的倍数。
数位\(DP\)
这题应该比较显然是一道 数位\(DP\) 题。
如何记录状态
这道题关键就在于如何记录状态,其余的就和普通的数位\(DP\)差不多了。
我们可以用\(f_{x,s1,s2}\)来表示还剩\(x\)位,这个数除末\(x\)位以外模\(7\)余\(s1\),这个数每一位之和除末\(x\)位以外模\(7\)余\(s2\)时所有与\(7\)无关的数的末\(x\)位的平方和。
但是,如果光光记录平方和,转移就有点困难了。
所以,我们先要来一点恶心的数学转化。
数学转化
让我们来研究一下\((x_1+t*10^y)^2+(x_2+t*10^y)^2+...+(x_n+t*10^y)^2\)这个式子。
先由完全平方公式可得:
\]
然后,我们将其去括号并重新组合,可得:
\]
如果用\(f(n)\)来表示\(x_1+x_2+...+x_n\),\(f^2(n)\)来表示\(x_1^2+x_2^2+...+x_n^2\),则:
\]
我们可以预处理出\(10^y\),并对于每个状态记录下\(n,f(n)\)和\(f^2(n)\),这样就可以实现\(O(1)\)转移了。
状态转移方程
用\(ns1\)来表示\((s1*10+i)\)%\(y\),\(ns2\)来表示\((s2+i)\)%\(y\)。
\]
\]
\]
代码
#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define abs(x) ((x)<0?-(x):(x))
#define INF 1e9
#define Inc(x,y) ((x+=y)>=MOD&&(x-=MOD))
#define MOD 1000000007
using namespace std;
LL n,m;
class FIO
{
private:
#define Fsize 100000
#define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
#define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
LL f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
public:
FIO() {FinNow=FinEnd=Fin;}
inline void read(LL &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));x*=f;}
inline void read_char(char &x) {while(isspace(x=tc()));}
inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
inline void write(LL x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
inline void write_char(char x) {pc(x);}
inline void write_string(string x) {register LL i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
inline void end() {fwrite(Fout,1,FoutSize,stdout);}
}F;
class Class_DigitalDP
{
private:
#define ten(x) ((x<<3)+(x<<1))
LL ans,len,num[20],tn[20];
struct key//记录一个状态
{
LL res,res_,tot;//res记录平方和,res_记录和,tot记录个数
key(LL x=0,LL y=0,LL z=-1):res(x%MOD),res_(y%MOD),tot(z%MOD){}
}f[20][7][7];
inline void Init(LL x) {len=0;while(x) num[++len]=x%10,x/=10;num[len+1]=0;}
inline key dfs(LL x,LL s1,LL s2,LL flag)
{
register LL i,lim=9,k;register key w=key(0,0,0),t;//w记录结果
if(!x) return key(0,0,s1&&s2);//如果x为0,返回结果
if(flag&&~f[x][s1][s2].tot) return f[x][s1][s2];//如果当前状态肯定在求解范围内,且已经访问并求解过当前状态,返回上次求解得到的答案
if(!flag) (num[x]^7&&(t=dfs(x-1,(ten(s1)+num[x])%7,(s2+num[x])%7,0),k=num[x]*tn[x-1]%MOD,w=key(t.res+(t.res_<<1)*k%MOD+t.tot*k%MOD*k%MOD,t.res_+t.tot*k%MOD,t.tot),true)),lim=num[x]-1;//对于不一定在求解范围内的值特殊处理
for(i=0;i<=lim;++i) if(i^7) t=dfs(x-1,(ten(s1)+i)%7,(s2+i)%7,1),k=i*tn[x-1]%MOD,w=key(w.res+t.res+(t.res_<<1)*k%MOD+t.tot*k%MOD*k%MOD,w.res_+t.res_+t.tot*k%MOD,w.tot+t.tot);//对每一个不为7的数字进行状态转移
if(flag) f[x][s1][s2]=w;//如果当前状态肯定在求解的范围内,就将求解出的答案记录下来,实现记忆化
return w;//返回求解出的答案
}
public:
Class_DigitalDP() {tn[0]=1;for(register LL i=1;i<20;++i) tn[i]=ten(tn[i-1])%MOD;}//预处理出10的幂
inline LL GetAns(LL x) {return !x?0:((void)(Init(x)),dfs(len,0,0,0).res);}//求解答案
}DigitalDP;
int main()
{
register LL i;register LL T;F.read(T);
while(T--) F.read(n),F.read(m),F.write(((DigitalDP.GetAns(m)-DigitalDP.GetAns(n-1))%MOD+MOD)%MOD),F.write_char('\n');
return F.end(),0;
}
【HDU4507】恨7不成妻(数位DP)的更多相关文章
- hdu4507吉哥系列故事——恨7不成妻 (数位dp)
Problem Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: ...
- HDU-4507 吉哥系列故事——恨7不成妻 数位DP
题意:给定区间[L, R]求区间内与7无关数的平方和.一个数当满足三个规则之一则认为与7有关:1.整数中某一位是7:2.整数的每一位加起来的和是7的整数倍:3.这个整数是7的整数倍: 分析:初看起来确 ...
- hdu-4507 吉哥系列故事——恨7不成妻 数位DP 状态转移分析/极限取模
http://acm.hdu.edu.cn/showproblem.php?pid=4507 求[L,R]中不满足任意条件的数的平方和mod 1e9+7. 条件: 1.整数中某一位是7:2.整数的每一 ...
- 【hdu4507】吉哥系列故事——恨7不成妻 数位dp
题目描述 求 $[L,R]$ 内满足:数位中不包含7.数位之和不是7的倍数.本身不是7的倍数 的所有数的平方和 mod $10^9+7$ . 输入 输入数据的第一行是case数T(1 <= T ...
- hdu4507 吉哥系列故事——恨7不成妻[数位DP]
这题面什么垃圾玩意儿 首先看到问题格式想到数位DP,但是求的是平方和.尝试用数位DP推出. 先尝试拼出和.设$f[len][sum][mod]$表示填到$len$位,已填位置数位和$sum$,数字取余 ...
- 吉哥系列故事——恨7不成妻(数位DP)
吉哥系列故事——恨7不成妻 http://acm.hdu.edu.cn/showproblem.php?pid=4507 Time Limit: 1000/500 MS (Java/Others) ...
- 几道数位DP
因为这几天写的几道数位DP大多都太水..而且也确实没什么好讲所以就扔到一起了. [hdu4772]Good Numbers 要求统计区间内 各位数之和能被10整除 的数的个数. 练手,f[i][j][ ...
- 数位DP复习笔记
前言 复习笔记第五篇.(由于某些原因(见下),放到了第六篇后面更新)CSP-S RP++. luogu 的难度评级完全不对,所以换了顺序,换了别的题目.有点乱,见谅.要骂就骂洛谷吧,原因在T2处 由于 ...
- 「算法笔记」数位 DP
一.关于数位 dp 有时候我们会遇到某类问题,它所统计的对象具有某些性质,答案在限制/贡献上与统计对象的数位之间有着密切的关系,有可能是数位之间联系的形式,也有可能是数位之间相互独立的形式.(如求满足 ...
- 2018.09.27 hdu4507吉哥系列故事——恨7不成妻(数位dp)
传送门 一道比较综合的数位dp. 维护三个值:[L,R][L,R][L,R] 区间中与7无关的数的数量,与7无关的数之和,与7无关的数的的平方和. 然后可以用第一个值推第二个,第一个和第二个值推第三个 ...
随机推荐
- 洛谷P2119 魔法阵
P2119 魔法阵 题目描述 六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量. 大魔法师有m个魔法物品,编号分别为1,2,...,m.每个物品具有一个魔法值,我们用Xi表示编 ...
- EIGRP-1-EIGRP的基础和演变
值得一提的是,在2013年,Cisco决定开放EIGRP的定义,并将其发布为IETFInternet草案,即RFC的前身:文档名称为draft-savage-eigrp.从此,基本的EIGRP不再是机 ...
- Jmeter分布式(转)jmeter -n -t baidu.jmx -l result.jtl -R 172.16.20.146:1099
1.准备2台在同一个局域网内的机器,一台作为master主控机,一台作为slave 执行机 master机器ip:172.16.20.134 slave机器ip:172.16.20.146 2.在2台 ...
- docker镜像的分层结构三
docker的镜像分层 docker里的镜像绝大部分都是在别的镜像的基础上去进行创建的,也就是使用镜像的分层结构. 实验 比如说使用dockerfile去创建一个最简单的hello镜像.创建好对应的d ...
- 忘记mysql数据库密码时进行修改方法
长时间没有使用数据库了,或者把密码改完之后就忘了数据库密码,不能正常进入数据库,也无法修改密码,有一个简单的常用修改密码方式: 1.首先找到和打开mysql.exe和mysqld.exe所在的文件夹( ...
- java实现的各种hash加密
public class jiami { public static void main(String args[]){ String signString="Thank you!" ...
- new 和 delete 用法
1. 这两个其实是 C++ 语言标准库的库函数,原型分别如下: void *operator new(size_t); //allocate an object void *operator dele ...
- Python3.5 控制台日志输出,区分标准输出与错误输出
import logging import sys class ConsoleHandler(logging.Handler): terminator = '\n' def __init__(self ...
- Shell笔试题1
1.用Shell编程,判断一文件是不是块或字符设备文件,如果是将其拷贝到 /dev 目录下. #!/bin/bash#1.sh#判断一文件是不是字符或块设备文件,如果是将其拷贝到 /dev 目录下#f ...
- Java修饰符/关键字
修饰符分类: 权限修饰符:public.protected.default.private 其他修饰符:abstract.static.final.transient.volatile.native. ...