Codeforces Round #432 (Div. 2) D 850B Arpa and a list of numbers(gcd 枚举)

来源:互联网 发布:数据分析招聘网 编辑:程序博客网 时间:2024/05/09 02:34

一看到感觉是dp,但是dp也太难了呀,然后就滚了.
gcd的问题很多时候都是枚举,因为gcd其实是很难递推的一个东西,所以观察一下ai的范围,大概也能猜到.
那么我们枚举每一个gcd,当然,是素数啦,然后发现每一个gcd我们数列的值可以O(n)算出来,可是素数有很多,这样不够,那么我们怎么样更快呢,就是可以利用一个区间的思想,假设x/y=delta,也就是说,假设p是gcd的一个倍数,那么在p-delta~p的范围内的数,他们要变成p,而在p-gcd~p-delta-1范围内的数,就是要删除,对吧?所以我们预处理一下,就可以在O(1)内得到要删除的数字数量和要加的数字之和(注意两者不同,要处理两个数组).感觉这里很奇妙的就是以前的前缀和都是以下标来做数组,但是这里直接是以值来做数组,这样好处就是假如用下标,那么要找到是logn,但这里ai小,所以直接用,可以O(1)得到,第一次见呢.
(感觉D题还是太难了,我还是太菜了,写起来真的各种难,留下我丑陋的调试痕迹好了)

/*  xzppp  */#include <iostream>#include <vector>#include <cstdio>#include <string.h>#include <algorithm>#include <queue>#include <map>#include <string>#include <cmath>#include <bitset>#include <iomanip>using namespace std;#define FFF freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define MP make_pair#define PB push_backtypedef long long  LL;typedef unsigned long long ULL;typedef pair<int,int > pii;typedef pair<double,double > pdd;typedef pair<double,int > pdi;const int MAXN = 1e6+17;const int MAXM = 20;const int MAXV = 2*1e3+17;const int INF = 0x7fffffff;const LL INFF = 0x7fffffffffffffff;const int MOD = 1e9+7;LL prime[MAXN];LL vis[MAXN];LL cnt;void get(){    memset(vis, 0, sizeof(vis));    cnt=0;    for(int i=2;i<MAXN;i++){        if(!vis[i]){            prime[++cnt]=i;            for(int j=i+i;j<MAXN;j+=i){                vis[j]=1;            }        }    }}LL a[2*MAXN],c[2*MAXN],tms[2*MAXN],sum[2*MAXN];int main(){    #ifndef ONLINE_JUDGE     FFF    #endif    get();    LL n,x,y,gst= 0 ;    cin>>n>>x>>y;    for (int i = 0; i < n; ++i)    {        scanf("%lld",a+i);        tms[a[i]]++;        sum[a[i]]+=a[i];        gst = max(gst,a[i]);    }    for (int i = 1; i <= 2*MAXN; ++i)    {        tms[i]+=tms[i-1];        sum[i]+=sum[i-1];    }    LL ans = INFF,delta = x/y,ori = delta;    for (int i = 1; i <= cnt; ++i)    {        //cout<<prime[i]<<endl;        if(prime[i]>2*gst) break;        LL p = prime[i];        LL del=0,inc=0,sinc=0,temp=0;        for (LL j = p; j <= gst+p; j+=p)        {            if(delta<p-1)            {                del =  tms[j-delta-1] - tms[j-p];                inc =  sum[j-1] - sum[j-delta-1];                sinc = tms[j-1] - tms[j-delta-1];                //if(del<0) cout<<j-delta-1<<" asd "<<j-p<<endl;            }            else            {                inc = sum[j-1] - sum[j-p];                sinc = tms[j-1] - tms[j-p];                //if(inc<0) cout<<j-1<<" sec "<<j-p<<endl;                //cout<<j<<"  "<<inc<<"  "<<sinc<<endl;              }            //cout<<j<<"  "<<del<<"  "<<inc<<"  "<<sinc<<endl;            temp += del*x+(sinc*j-inc)*y;            //cout<<temp<<endl;        }        //LL temp = del*x + (sinc*p-inc)*y;        //cout<<"ans"<<temp<<endl;        ans = min(temp,ans);    }    cout<<ans<<endl;    return 0;}
阅读全文
0 0
原创粉丝点击