zoukankan      html  css  js  c++  java
  • xsy 1845

    from NOIP2016模拟题34

    Description

    给定一个长度(nle 10^6)的序列, 给定(A, B)
    给出一个序列,要求你通过如下两个操作使得序列中所有数的最大公约数大于1,每个操作最多使用一次
    1:删除一段连续的数,代价为删除的长度$*A $
    2:将任意多个数+1或-1,代价为 (B *)数的个数

    Analysis

    由于删除也至少留下一个数
    最后的gcd一定是a[1]-1,a[1],a[1]+1,a[n]-1,a[n],a[n]+1六个数中
    某个数的质因数的倍数

    Solution

    考虑每个可能的质因数:

    two_pointer搞出删除的区间
    其他用修改操作
    预处理出哪些数必须修改chg[i]
    哪些数必须删除must[i]
    若对当前two_pointer区间
    修改要修改的数优于区间删除
    就将左区间右移一下
    two_pointer移的时候要保证合法

    Code

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int M=1000007;
     
    inline int rd(){
        int x=0;bool f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
        for(;isdigit(c);c=getchar()) x=x*10+c-48;
        return f?x:-x;
    }
    int n;
    int a[M];
    int fac[M*12],cnt=0;
    LL A,B;
    LL chg[M];
    LL must[M];
    LL ans=9223372036854775807;
     
    void solve(int p){
        int i,l,r;
        for(i=1;i<=n;i++){
            chg[i]=must[i]=0;
            if (a[i] % p == 0) continue;
            if((a[i]+1)%p==0||(a[i]-1)%p==0) chg[i]=1;
            else if(a[i]%p) must[i]=1;
        }
        for(i=1;i<=n;i++) chg[i]+=chg[i-1];
        for(i=1;i<=n;i++) must[i]+=must[i-1];
         
        for(l=1,r=1;r<=n;r++){//two_pointer求删除区间 
            if(must[n]-must[r]) continue;//不合法
            if(l==1&&r==n) l=2;//不能全删
            while(l<=r&&must[l]==0&&(chg[r]-chg[l-1])*B<=(r-l+1)*A) l++;//更优且移动和合法
            ans=min(ans,(chg[l-1]+chg[n]-chg[r])*B+(r-l+1)*A);
        }
    }
     
    void split(int x){
        for(int i=2;i*i<=x;i++){
            if(x%i==0) fac[++cnt]=i;
            while(x%i==0) x/=i;
        }
        if(x>2) fac[++cnt]=x;
    }
     
    int main(){
        int i;
        n=rd(),A=rd(),B=rd();
        for(i=1;i<=n;i++) a[i]=rd();
        split(a[1]); split(a[1]-1); split(a[1]+1);
        split(a[n]); split(a[n]-1); split(a[n]+1);
        sort(fac+1,fac+cnt+1);
        cnt=unique(fac+1,fac+cnt+1)-(fac+1);
        for(i=1;i<=cnt;i++)
            solve(fac[i]); 
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    python----面对对象三大特征2
    python---面对对象的三大特征
    python---面对对象的组合
    python----特殊闭包
    python----面向对象初识
    Nginx配置upstream实现负载均衡
    Nginx的配置与部署研究,Upstream负载均衡模块
    百度地图传经纬度位置显示
    ip转城市接口,ip转省份接口,ip转城市PHP方法
    PHP把采集抓取网页的html中的的&nbsp;去掉或者分割成数组
  • 原文地址:https://www.cnblogs.com/acha/p/6368426.html
Copyright © 2011-2022 走看看