【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.推导出来转移式就非常简单了. 在经过分析以后,我们 ...
随机推荐
- memcached 连接本地问题
刚开始学memcache ,就遇到一个问题. telnet 127.0.0.1 11211 回车之后就什么都没有提示了.然后不管设置什么都是报error . 表示不知道如何解决!先写个文章记录下来 ...
- 二进制搭建kubernetes多master集群【四、配置k8s node】
上一篇我们部署了kubernetes的master集群,参考:二进制搭建kubernetes多master集群[三.配置k8s master及高可用] 本文在以下主机上操作部署k8s node k8s ...
- 全国各地dns服务器列表
211.103.13.101 江苏省无锡市 移动DNS服务器 211.136.28.231 北京市 移动DNS服务器 211.136.28.234 北京市 移动DNS服务器 211.136.28.23 ...
- 进度条ProgressBar
在本节中,作者只写出了进度条的各种样式,包括圆形.条形,还有自定义的条形,我想如果能让条形进度条走满后再继续从零开始,于是我加入了一个条件语句.作者的代码中需要学习的是handler在主线程和子线程中 ...
- delete千万级别大表中的某部分数据
如果表很大--千万级别的数据,又不能做truncate 操作,只能 delete 表中某部分数据时可以用以下来执行,这种方式只对大表操作时比较有效率,数据量小时不考虑 --示例如下 declare c ...
- mysql图文安装教程(win7 32位 亲测)
一.下载mysql:http://www.mysql.com/downloads/ 弹出: 你需要有一个 Oracle Web 帐户,没有的话,注册一个: 勾选许可: 输入搜索条件: 下载MySQL ...
- mac windows蓝牙问题
如果是win7.win8或win10三者的64位版本,可以下载驱动解决:http://file2.mydrivers.com/2014/notebook/apple_broadcom_bluetoot ...
- Linux常见配置文件
一./etc 配置文件 /etc/passwd 用户数据库,其中的域给出了用户名.真实姓名.家目录.加密口令和用户的其他信息 /etc/group 类似/etc/passwd ,但说明的不是用户而是组 ...
- codevs 1012
题目描述 Description 给出n和n个整数,希望你从小到大给他们排序 输入描述 Input Description 第一行一个正整数n 第二行n个用空格隔开的整数 输出描述 Output De ...
- Android-Android7.0-java.lang.SecurityException: MODE_WORLD_READABLE no longer supported
某个AndroidProject项目在Android5.0系统运行是OK的,在Android7.0以上版本运行,报以下错误❌ 2019-01-02 15:33:39.996 17067-17067/? ...