zoukankan      html  css  js  c++  java
  • CF623B Array GCD

    CF623B Array GCD

    题目大意:

    给一个长为(n)的序列(v).有两操作如下:
    一:删除一段长为(m(m<n))的连续子序列,费用为(m*a).操作一只能执行一次.
    二:给一个数(+1/-1),费用为(b).每个数只能执行一次操作二.

    求使所有数最大公约数大于(1)的最小代价.

    题解:

    由于序列不能全部删完,所以最后必定会留下第一个数或最后一个数,而这两个数又能够加减(1)或保持不变,所以共有六种情况.
    我们枚举这六种情况,然后枚举质因子(x)进行(mathcal{DP}).
    我们先预处理出每个数(v)的代价(c).

    • (v%x==0)(c=0).
    • ((v+1)%x==0)((v-1)%x==0)(c=b)
    • 其它情况(c=inf)
      (dp)状态:(f[i][0/1/2])表示到第(i)个位置未删/在删/删完数的最小代价.则有转移方程如下:

    [f[i][0]=f[i-1][0]+c[i] ]

    [f[i][1]=min(f[i-1][0], f[i-1][1])+a ]

    [f[i][2]=min(f[i-1][1], f[i-1][2])+c[i] ]

    然后据此转移即可.

    
    const ll inf=1000000000000000LL, N=1e6+6;
    
    ll n, a, b;
    ll v[N];
    ll res=inf;
    
    ll c[N];
    ll f[N][3];
    inline void calc(ll x){
    	for (R ll i=1; i<=n; i++){
    		if (v[i]%x==0) c[i]=0;
    		else if (v[i]%x==1 || v[i]%x==x-1) c[i]=b;
    		else c[i]=inf;
    	}
    	for (R ll i=1; i<=n; i++){
    		f[i][0]=min(inf, f[i-1][0]+c[i]);
    		f[i][1]=min(inf, min(f[i-1][0], f[i-1][1])+a);
    		f[i][2]=min(inf, min(f[i-1][1], f[i-1][2])+c[i]);
    	}
    	chkmin(res, f[n][0]);
    	chkmin(res, f[n][1]);
    	chkmin(res, f[n][2]);
    }
    
    inline void solve(ll x){
    	for (R ll i=2; i<=100000; i++){
    		if (x%i==0){
    			calc(i);
    			while (x%i==0) x/=i;
    		}
    	}
    	if (x!=1) calc(x);
    }
    int main(){
    	read(n); read(a); read(b);
    	for (R ll i=1; i<=n; i++) read(v[i]);
    	for (R ll i=-1; i<=1; i++) solve(i+v[1]), solve(i+v[n]);
    	writeln(res);
    }
    
  • 相关阅读:
    测试clang-format的格式化效果
    debian设置limits.conf
    可读性公式的python包+MLTD讲解
    SQL-1
    首届中文NL2SQL挑战赛-step7记录
    首届中文NL2SQL挑战赛-step6
    torch学习中的难点
    yield and send的使用详细解释
    ELMO及前期工作 and Transformer及相关论文
    LSTM参数和结构的本质理解——num_units参数/batch_size/cell计算
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/14082481.html
Copyright © 2011-2022 走看看