bzoj4406: [Wc2016]论战捆竹竿&&uoj#172. 【WC2016】论战捆竹竿
第二次在bzoj跑进前十竟然是因为在UOJ卡常致死
首先这个题其实就是一个无限背包
一般做法是同余最短路,就是bzoj2118: 墨墨的等式可以拿到30分的好成绩
背包是个卷积就分治FFT优化那么下面20也没问题了 官方做法是大力bitset优化背包并且嘲讽了一波这个做法
再往后需要一个性质参见鏼爷的PPT
不想翻就直接看结论吧 对于一个串的所有border,它们组成不超过logn个等差数列
也就是说,对于所有增加长度的方式(其实就是period),可以分成logn组,每组是一个等差数列
考虑怎么利用这个性质
假设只有一个等差数列k+i*d,长度为c,我们直接拿首项作为的模数,k就被消掉了!
对于一个点x假如去更新别人,它可以更新到的就是x+(1~c-1)*d这些点
想象一下,x不停往前走d,根据同余的性质,一定会成环,而总共互不相交的环是gcd(k,d)个的
我们可以把每个环分开做,总共的点数是O(n)的
考虑对于一个环,它最小的那个点是不会被更新的,那么从这个点断开,对于每个点能够对它贡献的就是它在环上的前面c-1个点
设在模k意义下能够被表示出的最小值为f[0~k-1]
f[i]=min(f[i],f[j]+k+(i-j)*d)这个上一个单调队列就完事了
多个等差数列?
如果我们能改变模数保证正确性,那这个题就完事了
事实上就是可以
考虑模数由m变成n,设在模m意义下能够被表示出的最小值为f[0~m-1],在模n意义下能够被表示出的最小值为g[0~n-1]
这个时候,一步走n又变成有用的走法了(一步走m不行了,但是会在做的过程中被模掉就不管了)
先抛开这个不谈,直接先g[f[i]%n]=min(g[f[i]%n],f[i]),由于f对于m最小,在不考虑走n个情况下g也是最优的
考虑走n的贡献,其实是和一个等差数列去更新是同理的,找到最小位置断开,f[i]=min(f[i],f[j]+(i-j)*n),不用单调队列直接递推就可以了,因为如果i-1没有被更新一定是i-1更优,i-1被更新相当于i从更前面转移过来
坑点:
我都要哭了 谁在UOJ写hash谁傻逼啊!!!!! 狂交17发选手在线等死,假如hash底数太大还会被卡T,我真是****
不要像我一样老老实实的把border按2次幂划分,这样是严格nlogn的,会被卡成80。。。直接能插就插。。。。那个logn会变得**一样小(不知所措)
给个福利,把UOJ第9个点的构造思路放这(我hash被卡死自己找规律玩出来的),就是开始串中只有一个a,然后按以下步骤做18次:把这个串复制一份,然后翻转,当当前是进行该步骤的奇数次时,把这个复制的串按位取反(a变成b b变成a),然后接在原来的串后面,成为新的串
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath> #define min(x,y) (x<y?x:y)
#define ad(p,lim) ((p==lim)?1:p+1)
using namespace std;
typedef long long LL;
const int _=1e2;
const int maxn=*1e5+_;
const int mbit=;
LL inf;
int gcd(int a,int b)
{
if(a==)return b;
return gcd(b%a,a);
} //-------------------------------------def---------------------------------------------- char ss[maxn]; struct SSS
{
int k,d,c;//首项 公差 项数
SSS(){} SSS(int K,int D,int C){k=K,d=D,c=C;}
}s[maxn];int slen;
bool cmp(SSS s1,SSS s2){return s1.k<s2.k;}
int Log[maxn]; int p[maxn];
void getseq(int n)
{
int j=; p[]=;
for(int i=;i<=n;i++)
{
while(j!=&&ss[i]!=ss[j+])j=p[j];
if(ss[i]==ss[j+])j++;
p[i]=j;
}
slen=; int i=n;
do
{
i=p[i];
if(slen==|| s[slen].d!=-&&(n-i)-(s[slen].k+(s[slen].c-)*s[slen].d)!=s[slen].d )
s[++slen]=SSS(n-i,-,);
else
{
s[slen].c++;
if(s[slen].c==)s[slen].d=(n-i)-s[slen].k;
}
}while(i!=);
sort(s+,s+slen+,cmp);
} //----------------------------------getseq------------------------------------------------ int hlen,h[maxn],hp;//放环的
int mo,now,pre;LL f[][maxn];//对于当前模数余数等于i的数中,能够被表示出的第一个数
int tim,v[maxn];
void changemod(int nem)
{
int i;
for(i=;i<nem;i++)f[pre][i]=inf;
for(i=;i<mo;i++)
if(f[now][i]!=inf)f[pre][f[now][i]%nem]=min(f[pre][f[now][i]%nem],f[now][i]); int gg=gcd(mo,nem),k,j,u;
for(i=;i<gg;i++)
{
hlen=,h[hlen]=i,hp=;
u=mo%nem;k=i+u;if(k>=nem)k-=nem;
while(k!=i)
{
h[++hlen]=k;
if(f[pre][k]<f[pre][h[hp]])hp=hlen;
k+=u;if(k>=nem)k-=nem;
} k=hp,j=hp+;if(j==hlen+)j=;
while(j!=hp)
{
f[pre][h[j]]=min(f[pre][h[j]],f[pre][h[k]]+mo);
k=j,j++;if(j==hlen+)j=;
}
}
mo=nem;
} int head,tail,list[maxn];
void work(int sk,int sd,int sc)
{
if(sc==)return ; int gg=gcd(mo,sd),i,j,k,u,dis;
for(i=;i<gg;i++)
{
hlen=,h[hlen]=i,hp=;
u=sd%mo;k=i+u;if(k>=mo)k-=mo;
while(k!=i)
{
h[++hlen]=k;
if(f[now][k]<f[now][h[hp]])hp=hlen;
k+=u;if(k>=mo)k-=mo;
} head=tail=;list[]=hp;
j=hp+;if(j==hlen+)j=;
while(j!=hp)
{
dis=j-list[head];if(dis<)dis+=hlen;
while(head<=tail&&dis>sc-)
{
head++;
if(head<=tail){dis=j-list[head];if(dis<)dis+=hlen;}
}
f[now][h[j]]=min(f[now][h[j]],f[now][h[list[head]]]+sk+(LL)dis*sd); dis=j-list[tail];if(dis<)dis+=hlen;
while(head<=tail&&f[now][h[list[tail]]]>=f[now][h[j]]-(LL)dis*sd)
{
tail--;
if(head<=tail){dis=j-list[tail];if(dis<)dis+=hlen;}
}
list[++tail]=j;
j++;if(j==hlen+)j=;
}
}
} //------------------------------------solve---------------------------------------------- int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
int n;LL W;
scanf("%d%lld",&n,&W);W-=n;gets(ss+);
gets(ss+);
getseq(n); now=,pre=;
memset(f,,sizeof(f));f[now][]=; inf=f[][];
mo=s[slen].k,work(s[slen].k,s[slen].d,s[slen].c);
for(int i=slen-;i>=;i--)
{
changemod(s[i].k);
swap(now,pre);
work(s[i].k,s[i].d,s[i].c);
} LL ans=,num=W/mo,uli=W-num*mo;
for(int i=;i<mo;i++)
if(f[now][i]<=W)ans=ans+num+(i<=uli)-f[now][i]/mo;
printf("%lld\n",ans);
} return ;
}
bzoj4406: [Wc2016]论战捆竹竿&&uoj#172. 【WC2016】论战捆竹竿的更多相关文章
- UOJ#172. 【WC2016】论战捆竹竿 字符串 KMP 动态规划 单调队列 背包
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ172.html 题解 首先,这个问题显然是个背包问题. 然后,可以证明:一个字符串的 border 长度可 ...
- UOJ#172. 【WC2016】论战捆竹竿
传送门 首先这个题目显然就是先求出所有的 \(border\),问题转化成一个可行性背包的问题 一个方法就是同余类最短路,裸跑 \(30\) 分,加优化 \(50\) 分 首先有个性质 \(borde ...
- 【QQ技术】群文件报毒怎样下载?~ 变相绕过QQ复杂检验过程
刚才又人问我,要是群文件被鉴定为病毒那怎么下载? 我简单说一下吧: 其实qq客户端过滤比较严的,而web段却还是老一套,很多人说出现这个情况其实是腾讯已经把他库里面的文件删了,其实不然 如果源删了,那 ...
- mina编解码(摘录)
一.Mina对编解码的支持 我们知道网络通讯过程实际是对二进制数据进行处理的过程,二进制数据是计算机认识的数据.对于接收到的二进制数据我们需要将其转换成我们所熟悉的数据格式,此过程称为解码(decod ...
- NOIP 初赛笔记
// zj蒟蒻瑟瑟发抖.. // 停课了.要好好努力!——10月8日8:29于机房 1. 1946 年 美国 -> 第一台计算机 2. 真空电子管 -> 晶体管 -> 集成 -> ...
- [BZOJ3380] [USACO2004 Open]Cave Cows 1 洞穴里的牛之一
Description 很少人知道其实奶牛非常喜欢到洞穴里面去探险. 洞窟里有N(1≤N≤100)个洞室,由M(1≤M≤1000)条双向通道连接着它们.每对洞室间 至多只有一条双向通道.有K( ...
- Bzoj 3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一
3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 64 Solved ...
- 05:Cave Cows 1 洞穴里的牛之一
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 262144kB 描述 很少人知道其实奶牛非常喜欢到洞穴里面去探险. 洞窟里有N(1≤N≤100)个洞室,由 ...
- 恋恋山城 Jean de Florette (1986) 男人的野心 / 弗洛莱特的若望 / 让·德·弗罗莱特 / 水源 下一部 甘泉,玛侬
<让·德·弗洛莱特>电影剧本 文/[法]马赛尔·巴涅尔译/苏原 编者按:<让·德·弗洛莱特>和<甘泉,玛侬>是根据法国著名作家马赛尔·巴涅尔的同名小说改编的电影.马 ...
随机推荐
- tomcat设置去项目路径
1. 新建一个目录专门用于存放工程, 如: G:\apache-tomcat-6.0.20\project 2. 将工程存放到以上目录下:即:G:\apache-tomcat-6.0.20\proje ...
- 连通 OR 不连通(NOJ 1044)
比赛描述 给定一个无向图,一共n个点,请编写一个程序实现两种操作: D x y 从原图中删除连接x,y节点的边. Q x y 询问x,y节点是否连通 输入 第一行两个数n,m(5<=n<= ...
- 使用putty上传下载文件(pscp)
putty作为ssh工具开源免费,简单易用.可是如何使用它来上传和下载文件呢?答案在于pscp. pscp下载地址:http://www.chiark.greenend.org.uk/~sgtatha ...
- Cucumber Vs RobotFramework
I asked this same question a little over a year ago on this list when we were at your stage. Before ...
- Codeforces 487B Strip (ST表+线段树维护DP 或 单调队列优化DP)
题目链接 Strip 题意 把一个数列分成连续的$k$段,要求满足每一段内的元素最大值和最小值的差值不超过$s$, 同时每一段内的元素个数要大于等于$l$, 求$k$的最小值. 考虑$DP$ 设$ ...
- luogu P1351 联合权值
题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离. ...
- [NOIP2012T3]开车旅行
题目描述 NOIP 2012 提高组 题3小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 ...
- Codevs1062路由选择
/* #include<iostream> #include<cstdio> #include<cstring> #define MAXN 301 using na ...
- js监听鼠标点击操作
element.addEventListener('click', function() { /* do stuff here*/ }, false);
- github/gitlab ssh-keys全局唯一
我们知道,通过在gitlab.github上设置ssh-key,可以直接拉取代码:git clone …… 公司为了代码安全,会对代码访问权限进行控制,不同人有不同代码的访问权限. 有时候,为了临时获 ...