【CodeForces 624D/623B】Array GCD
You are given array ai of length n. You may consecutively apply two operations to this array:
- remove some subsegment (continuous subsequence) of length m < n and pay for it m·a coins;
- change some elements of the array by at most 1, and pay b coins for each change.
Please note that each of operations may be applied at most once (and may be not applied at all) so you can remove only one segment and each number may be changed (increased or decreased) by at most 1. Also note, that you are not allowed to delete the whole array.
Your goal is to calculate the minimum number of coins that you need to spend in order to make the greatest common divisor of the elements of the resulting array be greater than 1.
The first line of the input contains integers n, a and b (1 ≤ n ≤ 1 000 000, 0 ≤ a, b ≤ 109) — the length of the array, the cost of removing a single element in the first operation and the cost of changing an element, respectively.
The second line contains n integers ai (2 ≤ ai ≤ 109) — elements of the array.
Print a single number — the minimum cost of changes needed to obtain an array, such that the greatest common divisor of all its elements is greater than 1.
3 1 4
4 2 3
1
5 3 2
5 17 13 5 6
8
8 3 4
3 7 5 4 3 12 9 4
13
In the first sample the optimal way is to remove number 3 and pay 1 coin for it.
In the second sample you need to remove a segment [17, 13] and then decrease number 6. The cost of these changes is equal to 2·3 + 2 = 8 coins.
题意
给你n个数,可以执行两种操作最多各一次,一是移除一个连续的序列不可移动整个数列,代价是序列长度*a,二是选一些数改变1,即可以有的加一,有的减一,代价是数字个数*b
最终使得剩下所有数字的最大公约数大于1,求最少代价
分析
因为不能移除所有的数,所以a[1]和a[n]至少会有一个留下来,所以要在a[1]-1、a[1]、a[1]+1、a[n]-1、a[n]、a[n]+1六个数的所有质因数里找最大公约数。
找出t的所有质因子是j从2到根号t,如果t能整除j,j就是一个质因数,存起来,然后t一直除以j,除到不能整除为止,最后判断一下剩下的数如果大于1,那应该就是它本身了,那说明他就是一个素数,也要存起来。存的时候要注意不要重复。这样才不会超时,如果做素数表然后一个个素数去判断是不是它的因数就会超时。
找好后,对每个质因数,进行尺扫(或者叫尺取,还有种方法是DP(待补充)),左边扫到右边,预处理一下前i个数里有几个需要改变(bnum[i]),有几个必须移除的(anum[i])。
扫的时候,移除L到R这段区间的代价为aCost,不移除的代价为bCost,当bCost<=aCost时说明不用移除更划算,于是L更新为R+1,并且存下修改前面的数需要的代价oldbCost,否则计算一下只移除这段区间,其他区间通过修改达到目标,需要多少代价(oldbCost + aCost + ( bnum[n] - bnum[R] ) * b),然后更新答案。算代价的时候如果一个数必须移除,那修改的代价设为无穷。
代码
#include<stdio.h>
#include<algorithm>
#define ll long long
#define N 1000005
using namespace std;
ll n,a,b,m[N],p[N],bnum[N],anum[N],primeFactorNum,minc=1e18; void savePrime(ll a)
{
int noSaved=;
for(int i=; i<primeFactorNum && noSaved; i++)
if(a==p[i])
noSaved=;
if(noSaved)
p[primeFactorNum++]=a;
} void FindPrimeFactor(ll a)
{
for(int i=-; i<=; i++)
{
int j,t=a+i;
for(j=; j*j<=t; j++)
{
if(t%j==)
{
savePrime(j);
while(t%j==)t/=j;
}
}
if(t>)
savePrime(t);
}
} ll cost(ll num,ll factor)
{
if(num%factor==)
return ;
if( (num+) % factor && (num-) % factor )
return 1e17;//+1或-1都不能整除factor
return b;
} void solve(ll factor)
{
ll L=,R,bCost=,aCost=,oldbCost=; while( cost(m[L],factor) == && L <= n) L++;//左边过滤掉不需要改动的连续序列
if(L == n+)
{
minc=;
return;
}
R = L-; bnum[] = anum[] = ; for(int i=; i<=n; i++)
{
ll tmp=cost(m[i],factor); if(tmp == b)
bnum[i] = bnum[i-]+;
else
bnum[i] = bnum[i-]; if(tmp == 1e17)
anum[i] = anum[i-]+;
else
anum[i] = anum[i-];
} if(anum[n] == )
minc = min( minc, bnum[n] * b ); while(R<n)
{
aCost+=a;
R++;
if(bCost<1e17)
bCost+=cost(m[R],factor);
if(bCost<=aCost)
{
L=R+;
oldbCost+=bCost;
bCost=aCost=;
}
else
{
if(anum[n]-anum[R]==)
minc = min( minc , oldbCost + aCost + ( bnum[n] - bnum[R] ) * b );
}
}
}
int main()
{
scanf("%I64d%I64d%I64d",&n,&a,&b);
for(int i=; i<=n; i++)
scanf("%I64d",&m[i]); FindPrimeFactor(m[]);
FindPrimeFactor(m[n]); for(int i=; i<primeFactorNum && minc; i++)
solve(p[i]); printf("%I64d",minc);
return ;
}
2017/8/14,偶然看到自己这篇超长题解和代码,这题没那么烦吧。。因为六个月前的训练赛又挂了这题,然后重写的代码:
当时写得变量名真色。。我快看不懂了。。no代表一个都没删除的最小代价,be表示删除了第i个的最小代价,t就是删除了第i-1个的最小代价,ov就是有删除过但第i-1个未必删除了的最小代价。算是dp的思路。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ll long long
#define N 1000005
#define inf (1LL<<60)
using namespace std;
int n,c[N],d[],pr[N],cnt;
ll a,b;
int main() {
scanf("%d%lld%lld",&n,&a,&b);
for(int i=;i<=n;i++)
scanf("%d",&c[i]);
d[]=c[]-,d[]=c[]+;
d[]=c[n]-,d[]=c[n]+;
d[]=c[];d[]=c[n];
for(int i=;i<;i++){
for(int j=;j*j<=d[i];j++)
if(d[i]%j==){
pr[cnt++]=j;
while(d[i]%j==)
d[i]/=j;
}
if(d[i]>)pr[cnt++]=d[i];
}
sort(pr,pr+cnt);
int m=;
pr[m++]=pr[];
for(int i=;i<cnt;i++)if(pr[i]!=pr[i-])pr[m++]=pr[i];
ll ans=inf;
for(int i=;i<m;i++){
ll no=,be=,ov=;
for(int j=;j<=n;j++){
ll t=be;
be=min(no+a,be+a);
if(c[j]%pr[i]){
if((c[j]+)%pr[i]==||(c[j]-)%pr[i]==)
{
no+=b;
ov=min(min(ov+b,t+b),t+a);
}else{
no=inf;
ov=t+a;
}
}else{
ov=min(t,ov);
}
}
ans=min(ans,min(min(no,be),ov));
}
printf("%lld\n",ans);
return ;
}
【CodeForces 624D/623B】Array GCD的更多相关文章
- 【CodeForces 803 C】Maximal GCD(GCD+思维)
You are given positive integer number n. You should create such strictly increasingsequence of k pos ...
- 【Codeforces Rockethon 2014】Solutions
转载请注明出处:http://www.cnblogs.com/Delostik/p/3553114.html 目前已有[A B C D E] 例行吐槽:趴桌子上睡着了 [A. Genetic Engi ...
- 【CodeForces 624D】Array GCD
题 You are given array ai of length n. You may consecutively apply two operations to this array: remo ...
- 【57.97%】【codeforces Round #380A】Interview with Oleg
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- 【42.86%】【Codeforces Round #380D】Sea Battle
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- 【26.83%】【Codeforces Round #380C】Road to Cinema
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- 【17.76%】【codeforces round 382C】Tennis Championship
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 【21.21%】【codeforces round 382D】Taxes
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 【50.88%】【Codeforces round 382B】Urbanization
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
随机推荐
- JavaWeb学习总结-12 JSTL标签语言
一 JSTL JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能. JSTL支持通用的.结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签. 除了 ...
- Luogu3191 HNOI2007 紧急疏散 二分答案、最大流
传送门 题意:自己去看 考虑二分答案.$BFS$预处理出每一个人到每一扇门的最短时间,设二分的值为$mid$,那么把门拆成$mid$个点,每一个点代表第$1,2,...,mid$秒时的状态.$i-1$ ...
- ASP.NET Web API上实现 Web Socket - 转
1. 什么是Web Socket Web Socket是Html5中引入的通信机制,它为浏览器与后台服务器之间提供了基于TCP的全双工的通信通道.用以替代以往的LongPooling等comet st ...
- 两个非常好的bootstrap模板,外送大话设计模式!
两个非常好的bootstrap模板,外送大话设计模式! 下载地址:http://download.csdn.net/download/wolongbb/10198756
- [Oacle][Partition]Partition操作与 Index, Global Index 的关系
[Oacle][Partition]Partition操作与 Index, Global Index 的关系: ■ Regarding the local index and the global i ...
- Zookeeper Windows版的服务安装和管理工具
以前研究过负载均衡,最近正在项目上实施(从来没做过小项目以上级别的东西,哈).然后遇到了多个一模一样但是同时运行的服务.不同服务但依赖同相同的配置数据(前端网页服务:Nginx+IIS+nodejs. ...
- (代码篇)从基础文件IO说起虚拟内存,内存文件映射,零拷贝
上一篇讲解了基础文件IO的理论发展,这里结合java看看各项理论的具体实现. 传统IO-intsmaze 传统文件IO操作的基础代码如下: FileInputStream in = new FileI ...
- MongoDB日常运维操作命令小结
总所周知,MongoDB是一个NoSQL非数据库系统,即一个数据库可以包含多个集合(Collection),每个集合对应于关系数据库中的表:而每个集合中可以存储一组由列标识的记录,列是可以自由定义的, ...
- Mysql读写分离方案-MySQL Proxy环境部署记录
Mysql的读写分离可以使用MySQL Proxy和Amoeba实现,其实也可以使用MySQL-MMM实现读写分离的自动切换.MySQL Proxy有一项强大功能是实现"读写分离" ...
- ngx_pagespeed-nginx前端优化模块介绍
ngx_pagespeed是Nginx的一个扩展模块,借助pagespeed,为Nginx网站服务器提速.主要的功能是针对前端页面而进行服务器端的优化,对前端设计人员来说,可以省去优化css.js以及 ...