您的位置:首页 > 其它

codeforces 624d 623b Array GCD

2016-02-19 17:04 274 查看
过年玩了20天 

 都不会写了

题意:有两种操作,每种只能用一次,第一种对于一段连续区间进行移除(不能全删完),代价是长度*a,第二种是对于一些数进行+1或者-1,使得最后的剩余的最大公约数大于1

思路:由于不能全删完,所以至少会有一个数留着,这个数肯定会是头一个或最后一个,最大公约数肯定是在选中的这个数最后状态中的一个约数,而我们只要先枚举这个数是多少(一共6种),然后枚举他的素因子,用dp顺推即可。

#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#include<queue>
#include<math.h>
using namespace std;
#define LL long long
#define N 1000010
LL dp
[3];

int a
;

LL cost1,cost2;

int prime
;
int vis
;
int cnt;

int fac
;

void init()
{
for(int i=2;i<N;i++)
{
if(!vis[i])prime[cnt++]=i;
for(int j=0;j<cnt&&prime[j]*i<N;j++)
{
vis[prime[j]*i]=1;
if(i%prime[j]==0)break;
}
}
}

LL getAns(int st,int ed,int v)
{
memset(dp,0x3f,sizeof(dp));
//printf("%lld",dp[0][0]);
dp[st-1][0]=0;
for(int i=st;i<=ed;i++)
{
dp[i][1]=min(dp[i-1][0],dp[i-1][1])+cost1;
if(a[i]%v!=0)
{
if((a[i]+1)%v==0||(a[i]-1)%v==0)
{
dp[i][0]=dp[i-1][0]+cost2;
dp[i][2]=min(dp[i-1][1],dp[i-1][2])+cost2;
}
}
else
{
dp[i][0]=dp[i-1][0];
dp[i][2]=min(dp[i-1][1],dp[i-1][2]);
}
}
return min(min(dp[ed][0],dp[ed][1]),dp[ed][2]);
}

int factor(int x)
{
int tot=0;
for(int j=0;j<cnt&&x>=prime[j];j++)
{
if(x%prime[j]==0)
{
fac[tot++]=prime[j];
while(x%prime[j]==0)
x/=prime[j];
}
}
if(x!=1)
fac[tot++]=x;
return tot;
}

int main()
{
init();
int n;
scanf("%d%lld%lld",&n,&cost1,&cost2);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
LL ans=cost1*(LL)n;

for(int i=-1;i<=1;i++)
{
LL cost=i==0?0:cost2;

int siz=factor(a
+i);
for(int j=0;j<siz;j++)
ans=min(ans,getAns(1,n-1,fac[j])+cost);

siz=factor(a[1]+i);
for(int j=0;j<siz;j++)
ans=min(ans,getAns(2,n,fac[j])+cost);
}
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: