【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化

挺好的数位dp……
先说一下我个人的做法:
经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数
f[i]:所有数的所有未包含最后一位的子串的和
s[i]:所有数的所有后缀子串的和
c[i]:所有数的所有后缀子串的个数
n[i]:所有数共有多少个
他们的转移依次是(k为进制数)
f[i]=f[i-1]*k+s[i-1]*k
s[i]=s[i-1]*k*k+c[i-1]*k*(k-1)/2+n[i-1]*k*(k-1)/2
c[i]=c[i-1]*k+n[i-1]*k
n[i]=n[i-1]*k
我们发现对于最高位低于上界的数,我们可以在确定最高位上是1~9之后用上面的转移一遍O(n)dp算出来.如果最高位等于上界的话,我们的转移不太一样,但是也只不过是把某些k改为了这一位的上届,而且如果本位未达到上届,往后转移还是老样子,然而每次都要从前往后走一遍,会T,不过,这很明显是个可以用矩阵乘法优化的dp,因为他的转移方式每次都一样,所以我们就可以加速了,然而这是4*4的矩阵再加上一个log,吃不消啊,但是我们可以预处理转移i(1<=i<=max(n,m))次的矩阵,这样就可以做到O(4^3*n)了,又因为这个矩阵是个上三角矩阵,所以我们加一些矩阵乘法时的优化就可以有有着一个10左右常数的O(n)的做法了,我们解决了这道题!!!
现在说一下别人的做法:
A掉之后,去网上看了看别人的题解,发现从后往前递增并不是不可以,而且根本就没有人从前往后推,更没有任何人的做法跟矩阵乘法有半点关系……
他们就是从后往前递增,推出来一个关于k的次幂的式子,通过预处理k的次幂,加上对于上界的处理来递推……
他们的做法基本上都是O(n)的,但是跑得和我差不多……

#include <cstdio>
#include <cstring>
#include <algorithm>
char xB[(1<<15)+10],*xS,*xT;
#define gtc (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++)
template <typename _t>
inline void read(_t &x){register char ch=gtc;bool ud=false;for(x=0;ch<'0'||ch>'9';ch=gtc)if(ch=='-')ud=true;for(;ch>='0'&&ch<='9';x=(x<<1)+(x<<3)+ch-'0',ch=gtc);if(ud)x=-x;
}
typedef long long LL;
const int P=20130427;
const int N=100010;
int a[4][4],b[4],s[N][4][4],temp_a[4][4],temp_b[4],c[4],d[4];
inline void get(int x[][4],int y){memset(temp_a,0,sizeof(a));register int i,j,k;for(i=0;i<4;++i)for(j=0;j<4;++j)if(a[i][j])for(k=0;k<4;++k)if(x[j][k])temp_a[i][k]=(temp_a[i][k]+(LL)x[j][k]*a[i][j])%P;memcpy(s[y],temp_a,sizeof(s[y]));
}
inline void run(int x[][4]){memset(temp_b,0,sizeof(temp_b));register int i,j;for(i=0;i<4;++i)for(j=0;j<4;++j)if(x[i][j])temp_b[i]=(temp_b[i]+(LL)x[i][j]*d[j])%P;memcpy(c,temp_b,sizeof(c));
}
int bit,digit[N],k,n,m,len;
inline int calc(){int ans=0,i;d[3]=0,d[2]=(LL)k*(k-1)/2%P,d[1]=k-1,d[0]=k-1;for(i=1;i<bit;++i)run(s[i-1]),ans=(ans+c[3]+c[2])%P;memset(b,0,sizeof(b)),b[0]=1;for(i=bit;i>0;--i){d[0]=((LL)b[0]*(digit[i]-(i==bit))%P);d[1]=((LL)b[1]*(digit[i]-(i==bit))+d[0])%P;d[2]=((LL)k*b[2]%P*(digit[i]-(i==bit))+(LL)b[1]*((LL)digit[i]*(digit[i]-1)/2%P)+(LL)b[0]*((LL)digit[i]*(digit[i]-1)/2%P))%P;d[3]=((LL)b[3]*(digit[i]-(i==bit))+(LL)b[2]*(digit[i]-(i==bit)))%P;run(s[i-1]);ans=(ans+c[3]+c[2])%P;b[3]=(b[3]+b[2])%P;b[2]=((LL)k*b[2]+(LL)(b[1]+b[0])*digit[i])%P;++b[1];}return (ans+b[3]+b[2])%P;
}
int main(){read(k);int i,j,ans=0;a[3][3]=k,a[3][2]=k;a[2][2]=(LL)k*k%P,a[2][1]=((LL)k*(k-1)/2)%P,a[2][0]=((LL)k*(k-1)/2)%P;a[1][1]=k,a[1][0]=k;a[0][0]=k;s[0][0][0]=s[0][1][1]=s[0][2][2]=s[0][3][3]=1;for(read(n),i=n;i>0;--i)read(digit[i]);read(m),len=std::max(n,m);for(i=1;i<=len;++i)get(s[i-1],i);if(n==1)ans=(ans-(LL)digit[1]*(digit[1]-1)/2%P+P)%P;else{for(--digit[1],i=1;i<=n;++i)if(digit[i]<0)digit[i]+=k,--digit[i+1];else break;while(digit[n]==0)--n;bit=n,ans=(ans-calc()+P)%P;}for(i=m;i>0;--i)read(digit[i]);if(m==1)ans=(ans+(LL)digit[1]*(digit[1]+1)/2%P)%P;else bit=m,ans=(ans+calc())%P;printf("%d\n",ans);return 0;
}

 

转载于:https://www.cnblogs.com/TSHugh/p/8475491.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/453401.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zookeeper伪集群(在一台机器上集群)

2019独角兽企业重金招聘Python工程师标准>>> 创建一下的目录结构zookeeper-3.4.10是你下载的zookeeper的解压包 /zookeeper_cluster----/server_one|---/data|myid(文件)|---/datalog|---/zookeeper-3.4.10|---/bin|---/conf|---zoo.cfg|---..... |---/....----/ser…

mongo的php查询,使用PHP进行简单查询的mongo查询速度慢

我有一个非常简单的使用PHP执行的Mongo Query。我相信查询执行得非常快&#xff0c;因为当我在终端上运行它时&#xff0c;它几乎可以立即完成&#xff0c;并且当我解释()时&#xff0c;它表明它正在1-2ms内执行。但是&#xff0c;当我去迭代游标并将内容放入数组时&#xff0c…

顺序存储结构和链式存储结构的优缺点

&#xff08;一&#xff09;顺序存储结构和链式存储结构的优缺点比较&#xff0c;以及使用情况。 1 优缺点 ① 顺序存储时&#xff0c;相邻数据元素的存放地址也相邻&#xff08;逻辑与物理统一&#xff09;&#xff1b;要求内存中可用存储单元的地址必须是连续的。 优点&…

大话软件开发与开车的共同点

昨天路上开车&#xff0c;突然有了这个想法&#xff0c;做软件开发与开车&#xff0c;竟然有这么多的相似之处&#xff0c;大致整理了一下思路&#xff0c;和大家分享一下。 一、目的 开车的目的有3个&#xff0c;第一是为了让自己到底目的地(上班族)&#xff0c;第二是为了兜…

Spring核心接口之Ordered

一、Ordered接口介绍Spring中提供了一个Ordered接口。从单词意思就知道Ordered接口的作用就是用来排序的。Spring框架是一个大量使用策略设计模式的框架&#xff0c;这意味着有很多相同接口的实现类&#xff0c;那么必定会有优先级的问题。于是Spring就提供了Ordered这个接口&a…

将本地代码上传至github

注册github账号 https://github.com/ 安装git工具 https://git-for-windows.github.io 1.在github中创建一个项目 2.填写相应信息&#xff0c;点击create Repository name: 仓库名称 Description(可选): 仓库描述介绍 Public, Private : 仓库权限&#xff08;公开共享&#xff…

禅道 php api,云禅道有API的方式可以获取数据吗

api相关手册&#xff1a;api接口查看&#xff0c;可以本地搭建和云禅道相同版本的禅道&#xff0c;然后admin 后台 二次开发 api&#xff0c;可以查看接口列表。api调用步骤PATH_INFO方式1、访问 http://x.com/api-getsessionid.json获取禅道session信息2、使用上一步获取的ses…

链表的头结点和尾节点的用处

某些情况下设置尾指针的好处 尾指针是指向终端结点的指针&#xff0c;用它来表示单循环链表可以使得查找链表的开始结点和终端结点都很方便&#xff0c;设一带头结点的单循环链表&#xff0c;其尾指针为rear&#xff0c;则开始结点和终端结点的位置分别是rear->next->ne…

经验从哪里来?从痛苦中来!

1 刚才发博客&#xff0c;写的几百字丢失&#xff0c;让我知道下次一定要在记事本里写好&#xff0c;再复制过来&#xff0c;避免丢失了 2 程序忘记备份&#xff0c;辛苦一个多月的东西没有了&#xff0c;只能找到1月前的版本&#xff0c;让我知道了&#xff0c;重要的东西必须…

oracle 加全文索引,Oracle创建全文索引

1、创建表空间&#xff0c;有必要将物理文件设置大一些2、创建基于这个表空间的用户3、创建需要建立全文索引的表4、用管理员帐户为使用这用户开发ctx_ddl权限grant execute on ctx_ddl to useer;5、创建适合的lexer(解析器)exec ctx_ddl.create_references(my_lexer,basic_le…

机器视觉系统需要考虑的十个问题

为了使用户在选择一款机器视觉系统时应该考虑的关键的、基本的特性方面提供指导。下面是选择一款机器视觉系统时要优先考虑的十个方面&#xff1a; 1. 定位器 对象或特征的精确定位是一个检测系统或由视觉引导的运动系统的重要功能。传统的物体定位采用的是灰度值校正来识别物体…

严蔚敏数据结构:链表实现一元多项式相加

一、基本概念 1、多项式pn(x)可表示成: pn(x)a0a1xa2x2…anxn。 listP{&#xff08;a0&#xff0c;e0&#xff09;&#xff0c;(a1&#xff0c;e1)&#xff0c;(a2&#xff0c;e2)&#xff0c;…&#xff0c;(an&#xff0c;en) }。在这种线性表描述中&#xff0c;各个结点…

Java二十三设计模式之------工厂方法模式

一、工厂方法模式&#xff08;Factory Method&#xff09; 工厂方法模式有三种 1、普通工厂模式&#xff1a;就是建立一个工厂类&#xff0c;对实现了同一接口的一些类进行实例的创建。首先看下关系图&#xff1a; 举例如下&#xff1a;&#xff08;我们举一个发送邮件和短信的…

无法转化为项目财富的技术或功能就是垃圾

技术人员可能有个习惯&#xff0c;也可以叫通病&#xff0c;发现一个新技术&#xff0c;或者新的想法&#xff0c;会把某个现有的东西做的更好&#xff0c;或者可以增加某个功能让系统看上去更完美。 如果这是一个产品&#xff0c;那么大家都会鼓励你去做&#xff0c;如果我们…

ibatis oracle function,IBATIS调用oracle function(函数)的步骤实例

IBATIS调用oracle function(函数)的方法实例引用create or replace function getClassifiedCode(p_planCode in varchar2 -- 险种代码,p_usageAttributeCode in varchar2 -- 使用性质代码,p_ownershipAttributeCode in varchar2 -- 所属性质代码,p_vehicleTypeCode in varchar2…

一元多项式乘法算法

我认为大致算法应该是这样的: 首先准备一个空的链表L。利用第一个多项式的的指针所指的节点数值乘以多项式二的每一项&#xff0c;将结果保存在链表L中。 然后将指向该节点的指针后移到下一个节点继续进行乘法运算&#xff0c;将所得结果加到L中&#xff08;这个操作已经在一…

堆以及stl堆的使用

概念 性质: 1.堆是一颗完全二叉树&#xff0c;用数组实现。    2.堆中存储数据的数据是局部有序的。 最大堆&#xff1a;1.任意一个结点存储的值都大于或等于其任意一个子结点中存储的值。      2.根结点存储着该树所有结点中的最大值。 最小堆&#xff1a;1.任意一个结…

读【36岁IT老人再次随笔】的读后感,你会哪些计算机语言?

论坛首页一篇&#xff1a;社区“揭穿最大谎言”事件 &#xff0c; 我看了&#xff0c;也顺便看了里面另一位仁兄的【36岁IT老人再次随笔】 其中关键的地方就是一个例子&#xff1a;你会哪些计算机语言&#xff1f; 这个问题很有意思&#xff0c;确实如网友回复里说到的&#xf…

php接收vue请求数据axios,详解vue axios用post提交的数据格式

Content-type的几种常见类型一、是什么&#xff1f;是Http的实体首部字段&#xff0c;用于说明请求或返回的消息主体是用何种方式编码&#xff0c;在request header和response header里都存在。二、几个常用类型&#xff1a;1、application/x-www-form-urlencoded这应该是最常见…

数据结构中的逻辑结构简介

数据的逻辑结构是对数据之间关系的描述&#xff0c;有时就把逻辑结构简称为数据结构。逻辑结构形式地定义为&#xff08;K&#xff0c;R&#xff09;&#xff08;或&#xff08;D&#xff0c;S&#xff09;&#xff09;&#xff0c;其中&#xff0c;K是数据元素的有限集&#x…