挺好的数位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

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

  1. 【bzoj3329】Xorequ 数位dp+矩阵乘法

    题目描述 输入 第一行一个正整数,表示数据组数据 ,接下来T行 每行一个正整数N 输出 2*T行 第2*i-1行表示第i个数据中问题一的解, 第2*i行表示第i个数据中问题二的解, 样例输入 1 1 ...

  2. 形态形成场(矩阵乘法优化dp)

    形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...

  3. 【Contra】 矩阵乘法优化 dp

    偶然间,chnlich发现了他小时候玩过的一个游戏"魂斗罗",于是决定怀旧.但是这是一个奇怪的魂斗罗MOD.有N个关卡,初始有Q条命.每通过一个关卡,会得到u分和1条命,生命上限为 ...

  4. P3193-[HNOI2008]GT考试【KMP,dp,矩阵乘法】

    正题 题目链接:https://www.luogu.com.cn/problem/P3193 题目大意 求有多少个长度为nnn的字符串不包含子串sss. 解题思路 考虑dpdpdp,用fi,jf_{i ...

  5. 并行程序设计方法实验(包括openmp、向量化实现pi计算、SPECOMP2012测试、矩阵乘法优化)

    目录 一.实验环境 二.专题一之积分计算圆周率 2.1向量优化 2.2 OpenMP优化 三.专题二之测试SPECOMP2012 3.1初步了解SPECOMP 3.2系统基本配置 3.3实践 3.3. ...

  6. 基于how-to-optimize-gemm初探矩阵乘法优化

    1. 前言 这次,我们来聊一个轻松一点的话题,那就是给你一个矩阵A和一个矩阵B,使用矩阵乘法获得目标矩阵C,相信大家都不难写出下面的代码: #define A( i, j ) a[ (i)*lda + ...

  7. CUDA 矩阵乘法优化

    这个完全是基础知识啊~~  哪不对 大佬们帮忙指出啊 CUDA 矩阵乘法优化手段详解 Naive 实现的分析:到底差在哪里? 笔者面试过不少具有 CUDA 编程经验的校招同学,当提问使用 CUDA 编 ...

  8. CUDA实例系列一: 矩阵乘法优化

    CUDA实例系列一----矩阵乘法优化 很多朋友在学习CUDA的时候都会面临一个题目----矩阵乘法, 这也是CUDA最广泛的应用之一. 本文将详细讲解如何利用GPU加速矩阵乘法的计算. 话不多说, ...

  9. OpenBLAS项目与矩阵乘法优化 | AI 研习社

    提起矩阵计算,学过<高等数学>的人可能都听过,但若不是这个领域的研究者,恐怕也只停在"听过"的程度.在矩阵计算领域,开源项目OpenBLAS影响巨大,除IBM.华为等巨 ...

最新文章

  1. Java常用四大线程池用法以及ThreadPoolExecutor详解
  2. tensorflow随笔-条件循环控制(2)
  3. php include file_包含与被包含(PHP include文件)
  4. MybatisPlus入门之介绍
  5. web服务器的基本应用
  6. Maven依赖方式引用UEditor的jar包
  7. 分区表学习三:分区表实际操作心得
  8. Python flask使用实例
  9. C语言变量d的定义法则,C语言变量命名规则(3页)-原创力文档
  10. 详解Python中的序列解包(2)
  11. select和其元素options
  12. 调用第三方接口发送短信
  13. Android如何进行反编译
  14. 使用国产化的TongWeb服务器使用手册
  15. Linux下结束进程的命令
  16. 从董明珠称格力将会接入鸿蒙系统,是否可以看出手机圈的不堪?
  17. PDMS软光刻加工过程
  18. 【详细】endnote中英文文献混排
  19. 典型知识图谱项目:FreeBase、WikiData、Schema.org、DBPedia、YAGO、WordNet、ConceptNet、BabelNet、Palantir
  20. COMMENT的简单介绍,,及在Navicat中COMMENT的使用方法

热门文章

  1. mysql根据idb还原数据_mysql通过idb文件,恢复数据库
  2. 【牛客 - 188D 】愤怒(01滚动数组优化dp,括号匹配方案个数,tricks)
  3. *【CodeForces - 195B】After Training (多解,模拟)
  4. 吴恩达机器学习作业(3):逻辑回归
  5. js php c语言for循环,小蚂蚁学习C语言(8)——C语言for循环
  6. 一加6怎么刷android p6,一加6秒速跟进安卓P 教你尝鲜速成开发者
  7. 基于element-ui,vue的html随机点名器
  8. mysql innodb id_MySQL InnoDB row_id边界溢出验证的方法步骤
  9. leetcode574. 当选者(SQL)
  10. Abstract Self-Balancing Binary Search Tree