刷了这么久的数位 dp ,照样被这题虐,还从早上虐到晚上,对自己无语...(机房里又是只有我一个人,寂寞。)

题目:洛谷P3281 [SCOI2013]数数

题目描述

Fish 是一条生活在海里的鱼,有一天他很无聊,就开始数数玩。他数数玩的具体规则是:

  1. 确定数数的进制B

  2. 确定一个数数的区间[L, R]

  3. 对于[L, R] 间的每一个数,把该数视为一个字符串,列出该字符串的每一个(连续的)子串对应的B进制数的值。

  4. 对所有列出的数求和。现在Fish 数了一遍数,但是不确定自己的结果是否正确了。由于[L, R] 较大,他没有多余精力去验证是否正确,你能写一个程序来帮他验证吗?

输入输出格式

输入格式:

输入包含三行。

第一行仅有一个数B,表示数数的进制。

第二行有N +1 个数,第一个数为N,表示数L 在B 进制下的长度为N,接下里的N个数从高位到低位的表示数L 的具体每一位。

第三行有M+ 1 个数,第一个数为M,表示数R 在B 进制下的长度为M,接下里的M个数从高位到低位的表示数R 的具体每一位。

 

输出格式:

输出仅一行,即按照Fish 数数规则的结果,结果用10 进制表示,由于该数可能很大,输出该数模上20130427的模数。

分析:

数位 dp ,有点强大,又是一道需要感性理解的题目。。。

首先我们准备好 dp 状态: dp[i][2]  ,表示共有 i 位的 B 进制数,前缀子串的和。

dp[i][0] 表示无限制(甚至允许前导 0 的存在),

dp[i][1] 表示当前最高位不超过 d[i] (d[i] 表示读入的 B 进制数从后往前数的第 i 位)

那么 我们考虑 dp[i][0] 的转移:

假设当前 dp[i-1][0] 已经得到,那么 处理 dp[i][0] 就相当于 在 dp[i-1][0] 的基础上,在最高位(即第 i-1 位之前)加上一位 B 进制数 x 。

那么对于前缀子串的和来说,x 的贡献也就是让 后面的 i-1 个数字多了 x 中选择(0 ~ x-1),而 x 本身对于前缀子串和的贡献就是 x * B0 + x * B1 +.....+ x*Bi-1 (看不懂可以多想几遍,注意抓住贡献这个关键)

那么 我们就可以列出转移式子了:$$ dp[i][0] = B × dp[i−1][0]+ \drac{B(B−1)}{2} × B[i] × S[i−1] (B[i] = B^{i} , S[i] = \sum_{1}^{i} B[i]) $$

而对于有限制的 dp[i][1] 我们也可以对应的得到式子: $$ dp[i][1] = d[i] × dp[i−1][0]+\drac{d[i](d[i]−1)}{2} × B[i-1] × S[i-1] + dp[i−1][1] + d[i]∗(sub[i−1]+1) × S[i-1] ( d 的意义同上,sub[i] 表示读入的 B 进制数的长度为 i 的后缀子串对应值) $$

那么 对于 ans 的累加就是: $$ ans=\sum_{i=1}^{len} max(0,pre[i+1]−1) × f[i][0]+f[i][1] $$ 也就是说我们一步一步去处理 dp 数组,然后就可以同时累加答案了

为什么 ans 这样累加? 其实上面的式子就是在说,除去当前处理完的 i 位,剩下的(前缀子串对应值)有 pre[i+1] 种取法(因为可含前导零,所以方案数就是前缀子串对应数值)

但是前缀不能取到完全状态,于是 -1 。然后加上有限制的 dp[i][1] ,就是当前可累加的答案了 

emmmm...麻烦死了...其实不是很难理解,但是很难想到可以这么转移...之类的(都是借口)

于是...就可以上代码了吧?

代码

 //by Judge
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
#define int long long
using namespace std;
const int M=1e5+;
const ll mod=;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
int x=,f=; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-''; return x*f;
}
ll B,len,ans,d[M],f[M]={},sum[M]={},pre[M],sub[M],dp[M][];
inline void prep(){ //预处理
for(int i=,j;i<=1e5;++i)
f[i]=f[i-]*B%mod,
sum[i]=(sum[i-]+f[i])%mod; }
inline ll solv(){
ll ans=pre[len+]=; //恶心的pre初始化,最后的坑
for(int i=;i<=len;++i) sub[i]=(d[i]*f[i-]%mod+sub[i-])%mod;
for(int i=len;i>=;--i) pre[i]=(pre[i+]*B%mod+d[i])%mod;
//前缀值、后缀值的预处理
for(int i=;i<=len;++i){ //dp 转移,查了半天发现没毛病
dp[i][]=(dp[i-][]*B%mod+B*(B-)/%mod*f[i-]%mod*sum[i-]%mod)%mod;
dp[i][]=(dp[i-][]*d[i]%mod+d[i]*(d[i]-)/%mod*f[i-]%mod*sum[i-]%mod)%mod;
dp[i][]=(dp[i][]+dp[i-][]+d[i]*(sub[i-]+)%mod*sum[i-]%mod)%mod;
ans=(ans+max(0ll,pre[i+]-)*dp[i][]%mod+dp[i][])%mod;
} return ans;
}
signed main(){
B=read(),len=read(),prep();
for(int i=len;i;--i) d[i]=read();
for(int i=;i<=len;++i) //繁杂的数字处理,坑
if(d[i]){ --d[i]; break; }
else d[i]=B-;
if(!d[len]) --len;
ans=-solv(), len=read();
for(int i=len;i;--i) d[i]=read();
ans+=solv(),printf("%lld\n",(ans%mod+mod)%mod); return ;
}

洛谷:P3281 [SCOI2013]数数 (优秀的解法)的更多相关文章

  1. 【洛谷p1012】拼数

    (今天yuezhuren大课间放我们出来了……) (另外今天回了两趟初中部) 拼数[传送门] 洛谷算法标签: (然鹅这两个学的都不好,能过真的how strange) 开始的时候没读题啊,直接暴力so ...

  2. 【洛谷p1106】删数问题

    (洛谷t2755暂时过不去了) 删数问题[传送门] 洛谷算法标签: emmmm……删数问题又牵扯到了字符串.因为毕竟高精度的数240位呢!要是输入一个整型,要码240行来求出每一位……怕是还没求出来就 ...

  3. BZOJ2120/洛谷P1903 [国家集训队] 数颜色 [带修改莫队]

    BZOJ传送门:洛谷传送门 数颜色 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R ...

  4. 洛谷P4587 [FJOI2016]神秘数(主席树)

    题面 洛谷 题解 考虑暴力,对于询问中的一段区间\([l,r]\),我们先将其中的数升序排序,假设当前可以表示出\([1,k]\)目前处理\(a_i\),假如\(a_i>k+1\),则答案就是\ ...

  5. DP,数论————洛谷P4317 花神的数论题(求1~n二进制中1的个数和)

    玄学代码(是洛谷题解里的一位dalao小粉兔写的) //数位DP(二进制)计算出f[i]为恰好有i个的方案数. //答案为∏(i^f[i]),快速幂解决. #include<bits/stdc+ ...

  6. BZOJ1026或洛谷2657 [SCOI2009]windy数

    BZOJ原题链接 洛谷原题链接 简单的数位\(DP\),套模板就好. #include<cstdio> #include<cstring> using namespace st ...

  7. 洛谷P4317 花神的数论题

    洛谷题目链接 数位$dp$ 我们对$n$进行二进制拆分,于是就阔以像十进制一样数位$dp$了,基本就是套模板.. 接下来是美滋滋的代码时间~~~ #include<iostream> #i ...

  8. 洛谷 P1903 [国家集训队]数颜色 解题报告

    P1903 [国家集训队]数颜色 题目描述 墨墨购买了一套\(N\)支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1.Q L R代表询问你从第\(L\) ...

  9. 洛谷 P1015 回文数 Label:续命模拟QAQ

    题目描述 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. 例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数. 又如:对于10进制数 ...

随机推荐

  1. samba服务器之无认证进入共享目录

    修改设备中的/log/samba/lib/smb.conf文件 security = share [web]                                               ...

  2. Java Service Wrapper 使用

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sinat_26279177/article/details/70807173 1       简介 ...

  3. Asp.net+WebSocket+Emgucv实时人脸识别

    上个月在网上看到一个用web实现简单AR效果的文章,然后自己一路折腾,最后折腾出来一个 Asp.net+WebSocket+Emgucv实时人脸识别的东西,网上也有不少相关资料,有用winform的也 ...

  4. MyBatis SQL语句操作Mysql

    本文记录使用Mybatis操作数据库时碰到的一些语句,供以后参考. 一,多条件查询 示意SQL语句:SELECT t_field1, t_field2 FROM table_name WHERE t_ ...

  5. jquery.easing 和 jquery.transit 动画插件的使用

    从jQuery API 文档中可以知道,jQuery自定义动画的函数.animate( properties [, duration] [, easing] [, complete] )有四个参数: ...

  6. List<string>序列化与反序列化一个小坑

    Newtonsoft序列化与反序列化有两个重载方法,带<T>和不带<T>的 如果将一个List<String>序列化为jsonStr后,再反序列化,会变成JArra ...

  7. PHP的核心配置详解

    1.PHP核心配置详解 代码在不同的环境下执行的结果也会大有不同,可能就因为一个配置问题,导致一个非常高危的漏洞能够利用:也可能你已经找到的一个漏洞就因为你的配置问题,导致你鼓捣很久都无法构造成功的漏 ...

  8. 利用ssh操控远程服务器

    这里的”远程”操控的方法实际上也不是真正的远程.,這此操作方法主要是在一个局域网内远程操控电脑 (在一个路由器下).可以把它做成在互联网中的远程操控, 不过技术难度上加了一个等级, 如果你想是想人在公 ...

  9. Sqlserver 连接oracle和mysql数据库 已经oracle导入sqlserver表数据

    SQL Server2012创建连接服务器到ORACLE11G 8,百思考不知道原因啊??突然我发现如下:链接服务器—〉访问接口—〉OraOLEDB.Oracle—〉允许进程内没有勾上,但是我想上面的 ...

  10. spring boot 与 spring cloud 关系

    公司使用spring cloud,所以稍微了解一下 看了一下spring官网对 spring boot 以及 spring cloud 的解释 Spring Boot Spring Boot make ...