挺好的数位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[(<<)+],*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=;ch<''||ch>'';ch=gtc)if(ch=='-')ud=true;
for(;ch>=''&&ch<='';x=(x<<)+(x<<)+ch-'',ch=gtc);
if(ud)x=-x;
}
typedef long long LL;
const int P=;
const int N=;
int a[][],b[],s[N][][],temp_a[][],temp_b[],c[],d[];
inline void get(int x[][],int y){
memset(temp_a,,sizeof(a));
register int i,j,k;
for(i=;i<;++i)
for(j=;j<;++j)
if(a[i][j])
for(k=;k<;++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[][]){
memset(temp_b,,sizeof(temp_b));
register int i,j;
for(i=;i<;++i)
for(j=;j<;++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=,i;
d[]=,d[]=(LL)k*(k-)/%P,d[]=k-,d[]=k-;
for(i=;i<bit;++i)
run(s[i-]),ans=(ans+c[]+c[])%P;
memset(b,,sizeof(b)),b[]=;
for(i=bit;i>;--i){
d[]=((LL)b[]*(digit[i]-(i==bit))%P);
d[]=((LL)b[]*(digit[i]-(i==bit))+d[])%P;
d[]=((LL)k*b[]%P*(digit[i]-(i==bit))+(LL)b[]*((LL)digit[i]*(digit[i]-)/%P)+(LL)b[]*((LL)digit[i]*(digit[i]-)/%P))%P;
d[]=((LL)b[]*(digit[i]-(i==bit))+(LL)b[]*(digit[i]-(i==bit)))%P;
run(s[i-]);
ans=(ans+c[]+c[])%P;
b[]=(b[]+b[])%P;
b[]=((LL)k*b[]+(LL)(b[]+b[])*digit[i])%P;
++b[];
}
return (ans+b[]+b[])%P;
}
int main(){
read(k);int i,j,ans=;
a[][]=k,a[][]=k;
a[][]=(LL)k*k%P,a[][]=((LL)k*(k-)/)%P,a[][]=((LL)k*(k-)/)%P;
a[][]=k,a[][]=k;
a[][]=k;
s[][][]=s[][][]=s[][][]=s[][][]=;
for(read(n),i=n;i>;--i)read(digit[i]);
read(m),len=std::max(n,m);
for(i=;i<=len;++i)get(s[i-],i);
if(n==)ans=(ans-(LL)digit[]*(digit[]-)/%P+P)%P;
else{
for(--digit[],i=;i<=n;++i)
if(digit[i]<)digit[i]+=k,--digit[i+];
else break;
while(digit[n]==)--n;
bit=n,ans=(ans-calc()+P)%P;
}
for(i=m;i>;--i)read(digit[i]);
if(m==)ans=(ans+(LL)digit[]*(digit[]+)/%P)%P;
else bit=m,ans=(ans+calc())%P;
printf("%d\n",ans);
return ;
}

【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化的更多相关文章

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

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

  2. 洛谷2151[SDOI2009]HH去散步(dp+矩阵乘法优化)

    一道良好的矩阵乘法优化\(dp\)的题. 首先,一个比较\(naive\)的想法. 我们定义\(dp[i][j]\)表示已经走了\(i\)步,当前在点\(j\)的方案数. 由于题目中限制了不能立即走之 ...

  3. bzoj4870: [Shoi2017]组合数问题(DP+矩阵乘法优化)

    为了1A我居然写了个暴力对拍... 那个式子本质上是求nk个数里选j个数,且j%k==r的方案数. 所以把组合数的递推式写出来f[i][j]=f[i-1][j]+f[i-1][(j-1+k)%k].. ...

  4. BZOJ 3329: Xorequ [数位DP 矩阵乘法]

    3329: Xorequ 题意:\(\le n \le 10^18\)和\(\le 2^n\)中满足\(x\oplus 3x = 2x\)的解的个数,第二问模1e9+7 \(x\oplus 2x = ...

  5. bzoj 3329: Xorequ【数位dp+矩阵乘法】

    注意第一问不取模!!! 因为a+b=a|b+a&b,a^b=a|b-a&b,所以a+b=a^b+2(a&b) x^3x==2x可根据异或的性质以转成x^2x==3x,根据上面的 ...

  6. BZOJ.1875.[SDOI2009]HH去散步(DP 矩阵乘法)

    题目链接 比较容易想到用f[i][j]表示走了i步后到达j点的方案数,但是题目要求不能走上一条走过的边 如果这样表示是不好转移的 可以考虑边,f[i][j]表示走了i步后到达第j条边的方案数,那么有 ...

  7. BZOJ_1662_[Usaco2006 Nov]Round Numbers 圆环数_数位DP

    BZOJ_1662_[Usaco2006 Nov]Round Numbers 圆环数_数位DP Description 正如你所知,奶牛们没有手指以至于不能玩“石头剪刀布”来任意地决定例如谁先挤奶的顺 ...

  8. BZOJ_1026_[SCOI2009]windy数_数位DP

    BZOJ_1026_[SCOI2009]windy数_数位DP 题意:windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之 ...

  9. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

随机推荐

  1. php+mysql 数据库分表分段备份程序--宋正河

    <?php //宋正河 转载请注明出处 set_time_limit(0); header('content-type:text/html;charset=utf-8'); mysql_conn ...

  2. Kubernetes中的网络

    一.引子 既然Kubernetes中将容器的联网通过插件的方式来实现,那么该如何解决这个的联网问题呢? 如果你在本地单台机器上运行docker容器的话注意到所有容器都会处在docker0网桥自动分配的 ...

  3. Python之元类详解

    一.引子 元类属于Python面向对象编程的深层魔法,99%的人都不得要领,一些自以为搞明白元类的人其实也是自圆其说,点到为止,从队元类的控制上来看就破绽百出,逻辑混乱: 二.什么是元类 一切源自于一 ...

  4. Windows下用HackRF和SDR#收听FM

    本文内容.开发板及配件仅限用于学校或科研院所开展科研实验! 淘宝店铺名称:开源SDR实验室 HackRF链接:https://item.taobao.com/item.htm?spm=a1z10.1- ...

  5. uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)"解决办法

    如果在编译MFC程序的时候出现下列及类似的错误: 1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator ...

  6. 【视频编解码·学习笔记】12. 图像参数集(PPS)介绍

    一.PPS相关概念: 除了序列参数集SPS之外,H.264中另一重要的参数集合为图像参数集Picture Paramater Set(PPS). 通常情况下,PPS类似于SPS,在H.264的裸码流中 ...

  7. 华为笔试——C++最高分问题

    题目介绍:现在输入一组数据,写入学生的考试分数.已知学生数为N,学生编号为1到N,且0<N<=30000,每个学生都有一个分数:操作数为M且0<M<5000.输入第一行为N M ...

  8. 服务端模版注入漏洞检测payload整理

    服务端模版注入漏洞产生的根源是将用户输入的数据被模版引擎解析渲染可能导致代码执行漏洞 下表涵盖了java,php,python,javascript语言中可能使用到的模版引擎,如果网站存在服务端模版注 ...

  9. wc命令详解

    基础命令学习目录首页 原文链接:http://www.cnblogs.com/peida/archive/2012/12/18/2822758.html Linux系统中的wc(Word Count) ...

  10. 转载----C/C++ 中 const 修饰符用法总结

    感谢原创作者,写的好详细.不忍错过,所以转载过来了... 原文地址: https://www.cnblogs.com/icemoon1987/p/3320326.html 在这篇文章中,我总结了一些C ...