UOJ497 新年的复读机
题意
给定 \(n\) 个数 \(a_i\),你每次操作可以选择相邻两个数 \(a_i,a_{i+1}\),代价自加 \(a_i+a_{i+1}\),然后把这两个数删掉,并在原处添加一个 \(\gcd(a_i,a_{i+1})\),直到只剩一个数,你要最小化此时代价。
\(n\le2\times10^5,a_i\le 10^{12}\)
分析
考虑暴力区间 DP:设 \(f_{l,r}\) 表示消除 \([l,r]\) 的最小代价。复杂度 \(O(n^3)\)。
考虑一个重要性质:每次只往外扩展一个数不劣。
感性证明:考虑四个数 \(a_1,a_2,a_3,a_4\),我们要证的相当于 (((12)3)4) 和 (1(2(34))) 之中必定有一个比 ((12)(34)) 不劣。
首先将四个数同除它们的 gcd 没有影响。然后,令 \(x=\gcd(a_1,a_2,a_3),y=\gcd(a_2,a_3,a_4)\),不妨设 \(\gcd(a_1,a_2)=k_1x,\gcd(a_3,a_4)=k_4y\)。反证,若 (((12)3)4) 和 (1(2(34))) 都比 ((12)(34)) 劣,推推式子抵消一下发现 \(k_4y<x,k_1x<y\),两式相加得 \(k_1x+k_4y<x+y\),而 \(k_1,k_4\ge 1\),矛盾。
由此做到 \(O(n^2)\) 是容易的。
再考虑另一个重要性质:对于一个 \(l\),\(\gcd_{i=l}^r a_i\) 本质不同的 \(r\) 数量只有 \(O(\log V)\) 种。
证明:考虑 \(r\) 扩大时如果 gcd 变化,那么一定变化成原来 gcd 的一半。
如果此时把这些分界点拿出来,然后枚举初始点,直接 DP 状态数是 \(O(n\log^2 V)\) 的。考虑继续优化。
我们可以将 \(i\) 为左端点、右端点时把这些有用的区间拿出来,那么一共只有 \(O(n\log V)\) 个区间。
考虑对这些区间做 DP,首先将这些区间按照长度排序,桶排鸡排都行。
考虑能转移到 \(f_i\) 的状态,手玩一下实际上就是左端点的上一个区间和右端点的上一个区间,转移也比较好推。具体见 code。
最后介绍一下怎么求合法区间。
以固定右端点为例,考虑求出 \(r-1\) 时的分界点情况以及 gcd 值,然后加入 \(a_i\),将这些分界点的 gcd 值与 \(a_i\) 取 gcd,然后再加入一个单独的 \(a_i\),然后对这个玩意去重,为了方便,要保留左端点是 1 的区间。这样做的复杂度是 \(O(n\log^2 V)\) 的,据说可证成 \(O(n\log V)\),但我不会。实测这东西跑 1e6 跑的飞快,一般不是瓶颈,无需担心。
const int maxn=2e5+5,maxm=2e7+5,inf=0x3f3f3f3f;
const long long llinf=0x3f3f3f3f3f3f3f3f;
int n,a[maxn],s[maxn];
inline int gcd(int x,int y){
return !y?x:gcd(y,x%y);
}
struct seg{
int l,r,g;
}b[maxm];
int cnt;
pii q[maxn],qq[maxn];
int qcnt;
vector<seg>vec[maxn];
int lstl[maxn],lstr[maxn],f[maxm];
inline void solve_the_problem(){
n=rd();
rep(i,1,n)a[i]=rd(),s[i]=s[i-1]+a[i];
rep(i,1,n){
rep(j,1,qcnt)q[j].se=gcd(q[j].se,a[i]);
q[++qcnt]=mp(i,a[i]);
int pcnt=0;
per(j,qcnt,1){
if(q[j].fi==1||q[j].fi==i||q[j+1].se!=q[j].se){
qq[++pcnt]=q[j];
}
}
qcnt=pcnt;
rep(j,1,qcnt)q[j]=qq[qcnt-j+1];
rep(j,1,qcnt){
b[++cnt]=(seg){q[j].fi,i,q[j].se};
}
}
qcnt=0;
per(i,n,1){
rep(j,1,qcnt)q[j].se=gcd(q[j].se,a[i]);
q[++qcnt]=mp(i,a[i]);
int pcnt=0;
per(j,qcnt,1){
if(q[j].fi==n||q[j].fi==i||q[j+1].se!=q[j].se){
qq[++pcnt]=q[j];
}
}
qcnt=pcnt;
rep(j,1,qcnt)q[j]=qq[qcnt-j+1];
rep(j,1,qcnt){
b[++cnt]=(seg){i,q[j].fi,q[j].se};
}
}
rep(i,1,cnt){
vec[b[i].r-b[i].l+1].emplace_back((seg){b[i].l,b[i].r,b[i].g});
}
cnt=0;
rep(i,1,n){
for(auto j:vec[i])b[++cnt]=j;
vec[i].clear(),vec[i].shrink_to_fit();
}
rep(i,1,cnt){
const int l=b[i].l,r=b[i].r,L=lstl[l],R=lstr[r];
if(l==r){
lstl[l]=lstr[r]=i,f[i]=0;
continue;
}
f[i]=min(f[L]+b[L].g*(r-b[L].r)+s[r]-s[b[L].r],f[R]+b[R].g*(b[R].l-l)+s[b[R].l-1]-s[l-1]);
lstl[l]=lstr[r]=i;
}
write(f[cnt]);
}

浙公网安备 33010602011771号