Codeforces Round #236 (Div. 2)D题 Upgrading Array ;dp

来源:互联网 发布:视频会议软件 编辑:程序博客网 时间:2024/04/30 20:11

dp

给出一个序列,a1~an;给m个坏素数。不在这m个坏素数之内的素数称为好素数。

对于序列中的每个数,对应一个函数值f(s)满足:如果s的最小质因子p是好素数,则,否则

另外,我们可以进行以下操作:选择一个r(1<=r<=n),计算a[1]到a[r]的最大公约数g = GCD(a[1], a[2], ..., a[r]),令...

我们可以无限次的进行以上操作,问,通过这些操作,我们能得到的   sum=最大值是多少。

我们首先预处理出前缀gcd,(我的代码里时dpg[]),通过题意,我们知道,前面数字进行的操作比后面的多或者一样。所以我们从后往前判断是否要进行操作。每次进行操作时,我们对这个gcd分解质因子,判断它们之中有多少好素数,多少个坏素数,如果这个操作有利于提高我们的sum,就进行此操作,否则就不进行。

同时记录到达当前位置时,已经除去的数,我用dive[]记录。

这样,我们统计到一个数时,如果之后一个位置的数进行过操作,则当前位置的数必然也进行过相同的操作,所以,我们可以用gcd[i]/dive[i+1]表示前i个数当前最大的gcd,进行上面同样的判断,并记录dive[i]。

代码如下:

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define INF 200000000int dpg[5005],num[5005],dive[5005],prime[5005],n,m;int gcd(int a,int b){    if(a%b==0)        return b;    else        return gcd(b,a%b);}int max(int a,int b){    return a>b?a:b;}int min(int a,int b){    return a>b?b:a;}int judge(int x)     //判断进行除x的操作,值的变化{    int i,j,sum;    sum=0;    for(i=1;i<=m;i++)    {        if(x%prime[i]==0)        {            while(x%prime[i]==0)     //这里是看了别人的代码,感觉这种处理好坏素数的方法更好            {                x/=prime[i];                sum--;            }        }    }    for(i=2;i*i<=x;i++)    {        if(x%i==0)        {            while(x%i==0)            {                x/=i;                sum++;            }        }    }    if(x>1)    {        sum++;    }    return sum;}int main(){    int i,j,k,l,add,re;    while(scanf("%d%d",&n,&m)!=EOF)    {        for(i=1;i<=n;i++)        {            scanf("%d",&num[i]);            if(i==1)                dpg[i]=num[i];            else                dpg[i]=gcd(max(dpg[i-1],num[i]),min(dpg[i-1],num[i]));        }        for(i=1;i<=m;i++)            scanf("%d",&prime[i]);        dive[n+1]=1;        add=0;        for(i=1,re=0;i<=n;i++)            re+=judge(num[i]);        for(i=n;i>0;i--)        {            if(judge(dpg[i]/dive[i+1])<0)            {                dive[i]=dpg[i];                add-=(judge(dpg[i]));            }            else            {                dive[i]=dive[i+1];                add-=(judge(dive[i+1]));            }        }        printf("%d\n",re+add);    }    return 0;}


0 0