Problem

BZOJ

Solution

显然是一个同余系最短路问题,转移方案就是所有|S|-border的长度,有 \(O(n)\) 种,暴力跑dijkstra的复杂度为 \(O(n^2\log n)\) 。

有一个结论,一个字符串的border的长度可以被分为 \(\log |S|\) 个等差数列。

那么我们不如来考虑一个等差数列所造成的影响,设等差数列共有 \(m\) 项,初值为 \(x\) ,那么它可以被表示为 \(\{ kd+x,k\in[0,m)\}\)

\[f[i]=\min_{j=0}^{m-1}(f[(i-x-jd)\bmod n]+x+jd)
\]

如果我们能建立一个 \(\bmod x\) 的剩余系,那么接下来就相当于添加了一个 \(+d\) 的转移方案,但是这个转移有距离的限制。注意到能相互更新的状态会形成 \(\gcd(x,d)\) 个环,可以套路地拆下来并倍长,用单调队列即可解决距离的限制,时间复杂度为 \(O(x)\)。

那么就只需要解决两个剩余系相互转化的问题了。其实很简单,设旧表的模数为 \(p\),新表的模数为 \(q\),只需要把旧表中每一列的最小能表达的值作为初始值放入新表中,然后只需要把转移方案 \(+p\) 加入表中,更新一次即可,这样的复杂度是 \(O(q)\) 的。

总的时间复杂度为 \(O(\sum n\log n)\)

注意把用来存border的数组,把a[len+1]的值清为0,这样才不会导致判的等差数列。

Code

#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=500010;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
int z,n,k,tot,top,now,nxt[maxn],a[maxn],stk[maxn<<1];
int l,r,q[maxn<<1];
ll w,ans,f[maxn],g[maxn];
char s[maxn];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
void trans(int x)
{
int D=gcd(x,now);
memset(g,0x3f,x<<3);
for(int i=0;i<now;i++) getmin(g[f[i]%x],f[i]);
for(int i=0;i<D;i++)
{
top=0;
for(int j=i;top==0||j!=i;j=(j+now)%x) stk[++top]=j;
for(int j=1;j<=top;j++) stk[j+top]=stk[j];
top<<=1;
for(int j=2;j<=top;j++)
getmin(g[stk[j]],g[stk[j-1]]+now);
}
memmove(f,g,x<<3);
now=x;
}
void solve(int x,int d,int m)
{
trans(x);
if(d<0) return ;
int D=gcd(x,d);
for(int i=0;i<D;i++)
{
top=0;l=1;r=0;
for(int j=i;top==0||j!=i;j=(j+d)%x) stk[++top]=j;
for(int j=1;j<=top;j++) stk[j+top]=stk[j];
top<<=1;
for(int j=1;j<=top;j++)
{
while(l<=r&&j-q[l]>=m) ++l;
if(l<=r) getmin(f[stk[j]],f[stk[q[l]]]+(j-q[l])*d+x);
while(l<=r&&f[stk[q[r]]]+(j-q[r])*d>f[stk[j]]) --r;
q[++r]=j;
}
}
}
int main()
{
read(z);
while(z--)
{
read(n);read(w);scanf("%s",s);
ans=tot=k=0;memset(f,0x3f,n<<3);
for(int i=1;i<n;i++)
{
while(k&&s[k]!=s[i]) k=nxt[k];
if(s[k]==s[i]) nxt[i+1]=++k;
else nxt[i+1]=0;
}
for(int i=nxt[n];i;i=nxt[i]) a[++tot]=n-i;
now=n;f[0]=n;a[tot+1]=0;
for(int i=1,j=1;i<=tot;i=j)
{
while(a[j+1]-a[j]==a[i+1]-a[i]) j++;
solve(a[i],a[i+1]-a[i],j-i);
}
for(int i=0;i<now;i++) if(f[i]<=w) ans+=(w-f[i])/now+1;
printf("%lld\n",ans);
}
return 0;
}

BZOJ4406 WC2016 论战捆竹竿的更多相关文章

  1. bzoj4406: [Wc2016]论战捆竹竿&&uoj#172. 【WC2016】论战捆竹竿

    第二次在bzoj跑进前十竟然是因为在UOJ卡常致死 首先这个题其实就是一个无限背包 一般做法是同余最短路,就是bzoj2118: 墨墨的等式可以拿到30分的好成绩 背包是个卷积就分治FFT优化那么下面 ...

  2. luogu P4156 [WC2016]论战捆竹竿

    传送门 官方题解(证明都在这) 神仙题鸭qwq 转化模型,发现这题本质就是一个集合,每次可以加上集合里的数,问可以拼出多少不同的数 首先暴力需要膜意义下的最短路,例题戳这 然后这个暴力可以优化成N^2 ...

  3. Luogu4156 WC2016 论战捆竹竿 KMP、同余类最短路、背包、单调队列

    传送门 豪华升级版同余类最短路-- 官方题解 主要写几个小trick: \(1.O(nm)\)实现同余类最短路: 设某一条边长度为\(x\),那么我们选择一个点,在同余类上不断跳\(x\),可以形成一 ...

  4. 「WC2016」论战捆竹竿

    「WC2016」论战捆竹竿 前置知识 参考资料:<论战捆竹竿解题报告-王鉴浩>,<字符串算法选讲-金策>. Border&Period 若前缀 \(pre(s,x)​\ ...

  5. UOJ#172. 【WC2016】论战捆竹竿 字符串 KMP 动态规划 单调队列 背包

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ172.html 题解 首先,这个问题显然是个背包问题. 然后,可以证明:一个字符串的 border 长度可 ...

  6. UOJ#172. 【WC2016】论战捆竹竿

    传送门 首先这个题目显然就是先求出所有的 \(border\),问题转化成一个可行性背包的问题 一个方法就是同余类最短路,裸跑 \(30\) 分,加优化 \(50\) 分 首先有个性质 \(borde ...

  7. 【WC2016】论战捆竹竿

    已经快三周了啊--终于把挖的坑填了-- 首先显然是把除了自身的所有border拿出来,即做 \(\left\{ n - b_1, n - b_2, \dots, n - b_k, n \right\} ...

  8. 【LuoguP4156】论战捆竹竿

    题目链接 题意简述 你有一个长度为 n 的字符串 , 将它复制任意次 , 复制出的串的前缀可以与之前的串的后缀重叠在一起 , 问最后总共可能的长度数目 , 长度不能超过 \(w\) 多组数据. \(n ...

  9. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

随机推荐

  1. SAS学习笔记51 SAS数据集

    结构 SAS数据集是关系型的,包含两个部分:描述部分(变量)和数据部分(观察值) 形式 SAS系统中共有两种类型的数据集: 1.SAS 数据文件(SAS datafiles) 2.SAS 数据视窗(S ...

  2. linux命令行删除N天前的数据的命令

    命令:  find . -mtime +N -type f -name "*.log.*" -exec rm -f {} \; 简单解释: find .查询  ; -mtime 规 ...

  3. javascript基本类型和对象

    JS 中分为七种内置类型,七种内置类型又分为两大类型:基本类型和对象(Object). 基本类型 null undefined boolean number string symbol 其中 JS 的 ...

  4. axios配置及使用(发起请求时带上token)

    1.安装 利用npm安装 npm install axios --save 2.引入即可使用 import axios from 'axios' 3.目录 4.各个文件设置: (1)env.js ex ...

  5. FICO-清帐函数

    转载:https://www.cnblogs.com/caizjian/p/8067071.html https://blog.csdn.net/sapliumeng/article/details/ ...

  6. 通过DB13备份SystemDB

    配置systemdb capital user name:SYSTEM save -back Save 现在可以通过DB13备份SystemDB Done. Congratulations!

  7. How to change SAPABAP1 schema password In HANA

    Symptom How to change SAPABAP1 schema password Environment HANA 1.x HANA 2.x Resolution Shutdown the ...

  8. C#-DBHelper

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. 缓存数据库memcache、redis原理对比

    一.问题:     数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求. 二.解决方案:      1.通过高速服务器Cache缓存数据库数据      2.内存数据库     (这里 ...

  10. cdh的web管理界面503

    503 Service Unavailable No server is available to handle this request.       重启 agent  以及 server