【xsy1611】 数位dp 数位dp

这题是显然的数位$dp$,然而我居然写了一个下午!!!
我们不难想到差分,令$solve(x,y)$表示从第一个数字在区间$[0,x]$,第二个数字在区间$[0,y]$的答案。
不难发现题目中给了你一对$A$,$B$,答案显然为$solve(B,B)-2solve(A-1,B)+solve(A-1,A-1)$。
考虑如何求解$solve(x,y)$函数,令$n=max(len(x),len(y))$,其中$len(p)$表示数字$p$在十进制下的长度(以下的位均代表十进制位)。
令$f[i]$表示数字$x$在模意义下前$i$位的值,令$F[i]$表示数字$x$在模意义下后$n-i+1$位的值。
同理,我们处理出$g[i]$和$G[i]$。
令$mi[i]$表示模意义下$10^i$的值,$Mi[i]$表示模意义下$10^(n-i+1)$的值。
令$ans[i][j][k]$表示第一个数字的第$i$位为$j$,第二个数字的第$i$位为$k$时的答案。
设第一个数字第$i$位为$j$的数字个数为$mul1$,第二个数字第$i$位为$k$的个数为$mul2$。
下面考虑如何求$mul1$,设$x[i]$为数字$x$的第i位,$num[i]$为数字$x$前$i$位构成的数,$Num[i]$为数字$x$后$i$位构成的数。
当$x[i]<j$时,$mul1=(f[i-1]+1)\times Mi[i+1]$,这里可以理解为前$i$位填一个数不大于$num[i-1]$的数,或者全填$0$,后$n-i$个数随便填的方案数。
当$x[i]==j$时,$mul1=f[i-1]\times Mi[i+1]+F[i+1]+1$ ,这里可以理解为前$i$位填一个小于$num[i-1]$的数,后$n-i$个数随便填的方案数,加上前$i$个数和$x$的前i个数相同,后n-i个数填写不大于F[i+1]的方案数。
当x[i]>j时,$mul1=f[i-1]\times Mi[i+1]$,这里可以理解为前$i$位填一个小于$num[i-1]$的数,后$n-i$位随便填的方案数。
求$mul2$同理
那么显然,$ans[i][j][k]=mul1\times mul2$。$solve(x,y)=\sum_{i=1}^{n}\sum_{j=0}^{9}\sum_{k=0}^{9}ans[i][j][k]$。
最终的答案为$solve(B,B)-2solve(A-1,B)+solve(A-1,A-1)$。考虑到$A$跟$B$的位数可能很大,这个减法需要用高精度。
完结撒花,注意细节。
#include<bits/stdc++.h>
#define MOD 1000000007
#define M 100005
#define LL long long
using namespace std;
char c[M]={};
struct bign{
LL a[M+],len; bign(){memset(a,,sizeof(a));}
void rd(){
scanf("%s",c); len=strlen(c);
for(LL i=;i<len;i++) a[M-i]=c[len-i-]-'';
}
void jian(){
for(LL i=M,g=;i&&g;i--){
LL s=a[i]-g;
if(s>=) a[i]=s,g=;
else a[i]=s+,g=;
}
for(LL i=;i<=M;i++)
if(a[i]!=){
len=M-i+;
return;
}
}
}A,B,L,R;
LL f[M]={},g[M]={},F[M]={},G[M]={},mi[M]={},Mi[M]={},a[M]={},b[M]={},n; LL solve(){
n=max(A.len,B.len); LL res=;
mi[]=; for(LL i=;i<=n;i++) mi[i]=mi[i-]*%MOD;
F[n+]=G[n+]=;
for(LL i=;i<=n;i++) a[i]=A.a[M-n+i],b[i]=B.a[M-n+i];
for(LL i=;i<=n;i++) f[i]=(f[i-]*+a[i])%MOD,g[i]=(g[i-]*+b[i])%MOD;
for(LL i=n;i;i--) F[i]=(F[i+]+a[i]*mi[n-i])%MOD,G[i]=(G[i+]+b[i]*mi[n-i])%MOD;
Mi[n+]=; for(LL i=n;i;i--) Mi[i]=Mi[i+]*%MOD; for(LL i=;i<=n;i++){
for(LL num1=;num1<;num1++)
for(LL num2=;num2<;num2++){
LL cha=abs(num1-num2),mul1=,mul2=;
if(num1<a[i]) mul1=(f[i-]+)*mi[n-i]%MOD;
if(num1==a[i]) mul1=(f[i-]*Mi[i+]%MOD+F[i+]+)%MOD;
if(num1>a[i]) mul1=f[i-]*Mi[i+]%MOD; if(num2<b[i]) mul2=(g[i-]+)*mi[n-i]%MOD;
if(num2==b[i]) mul2=(g[i-]*Mi[i+]%MOD+G[i+]+)%MOD;
if(num2>b[i]) mul2=g[i-]*Mi[i+]%MOD; res=(res+mul1*mul2%MOD*cha)%MOD;
}
}
return res;
} int main(){
L.rd(); R.rd();
LL ans=;
A=R; B=R;
ans=solve();
A=L; A.jian();
ans=(ans-*solve()+*MOD)%MOD;
B=L; B.jian();
ans=(ans+solve())%MOD;
cout<<ans<<endl;
}
【xsy1611】 数位dp 数位dp的更多相关文章
- [DP]数位DP总结
数位DP总结 By Wine93 2013.7 1.学习链接 [数位DP] Step by Step http://blog.csdn.net/dslovemz/article/details/ ...
- CodeForces 54C-First Digit Law(数位,概率dp)
题意: 给你n个区间,在每个区间里各取一个数(随机取),求这n个数中超过K%的数是首位为1数的概率 分析: dp[i][j]取前i个数,有j个是首位为1的数的概率 易知,dp[i][j]=dp[i-1 ...
- 数位dp模板 [dp][数位dp]
现在才想到要学数位dp,我是不是很弱 答案是肯定的 以一道自己瞎掰的题为模板 //题: //输入数字n //从0枚举到n,计算这n+1个数中含有两位数a的数的个数 //如12930含有两位数93 #i ...
- Codeforces Round #235 (Div. 2) D. Roman and Numbers 状压dp+数位dp
题目链接: http://codeforces.com/problemset/problem/401/D D. Roman and Numbers time limit per test4 secon ...
- Codeforces 946 课程表背包DP 数位DFS构造
A B 给你A,B 两个数 1.a=0 OR b=0 break 2.a>=2b a=a-2b 3.b>=2a b=b-2a 如果只是单纯模拟肯定会超时 ...
- DP套DP HDOJ 4899 Hero meet devil(国王的子民的DNA)
题目链接 题意: 给n长度的S串,对于0<=i<=|S|,有多少个长度为m的T串,使得LCS(S,T) = i. 思路: 理解的不是很透彻,先占个坑. #include <bits/ ...
- LightOJ1044 Palindrome Partitioning(区间DP+线性DP)
问题问的是最少可以把一个字符串分成几段,使每段都是回文串. 一开始想直接区间DP,dp[i][j]表示子串[i,j]的答案,不过字符串长度1000,100W个状态,一个状态从多个状态转移来的,转移的时 ...
- 377. Combination Sum IV——DP本质:针对结果的迭代,dp[ans] <= dp[ans-i] & dp[i] 找三者关系 思考问题的维度+1,除了数据集迭代还有考虑结果
Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...
- HDU4960Another OCD Patient(间隙dp,后座DP)
Another OCD Patient Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Ot ...
- [CF697D]Puzzles 树形dp/期望dp
Problem Puzzles 题目大意 给一棵树,dfs时随机等概率选择走子树,求期望时间戳. Solution 一个非常简单的树形dp?期望dp.推导出来转移式就非常简单了. 在经过分析以后,我们 ...
随机推荐
- C语言基础课第四次作业
1.实验代码 7-2 打印九九口诀表 (15 分) #include<stdio.h> #include<math.h> int main(void){ int a, ...
- JavaScript 静态方法和实例方法
总结: 直接定义在构造函数上的方法和属性是静态的, 定义在构造函数的原型和实例上的方法和属性是非静态的 静态方法: function ClassA(){ //定义构造函数 }; ClassA.fun ...
- 使用delphi 开发多层应用(二十三)KbmMW 的WIB
解释WIB 是什么之前,先回顾以下我们前面的各种服务工作方式.前面的各种服务的工作方式都是请求/应答方式. 客户端发送请求,服务器端根据客户端的请求,返回相应的结果.这种方式是一种顺序式访问,是一种紧 ...
- 2018.07.20 bzoj1614: Telephone Lines架设电话线(二分+最短路)
传送门 这题直接做显然gg" role="presentation" style="position: relative;">gggg,看这数据 ...
- 2018.07.13 [HNOI2015]落忆枫音(容斥原理+dp)
洛谷的传送门 bzoj的传送门 题意简述:在DAG中增加一条有向边,然后询问新图中一共 有多少个不同的子图为"树形图". 解法:容斥原理+dp,先考虑没有环的情况,经过尝试不难发现 ...
- APMServ—优秀的PHP集成环境工具
经常折腾wordpress和各种php开发的cms,免不了要在本地测试这些程序,所以选择一款好的php集成环境就至关重要啦.之前在月光博客上看到有一篇“常见的WAMP集成环境”介绍,然后先后试用过XA ...
- HDU 3247 Resource Archiver (AC自动机+BFS+状压DP)
题意:给定 n 个文本串,m个病毒串,文本串重叠部分可以合并,但合并后不能含有病毒串,问所有文本串合并后最短多长. 析:先把所有的文本串和病毒都插入到AC自动机上,不过标记不一样,可以给病毒标记-1, ...
- Python Sleep休眠函数
#!/usr/bin/env python import os import time def fun(name): write_name="command %s failed!\n&quo ...
- DOM数据解析
//DOM : Document Object Model ,一种XML解析的方式,先读取整篇的内容,然后再进行解析,解析速度比较快,如果内出现错误,解析就会失败,iOS不支持DOM解析,goole提 ...
- 磁盘配额(Quota)的应用与实践
1>什么是Quota 在Linux中,由于是多用户,多任务的环境,所以会有多用户共同使用一个硬盘空间的情况发生,如果其中有少数几个用户大量占用掉了硬盘空间的话,那肯定影响其他用户的使 ...