codeforces 402d Upgrading Array

81 篇文章 0 订阅
78 篇文章 0 订阅

http://www.elijahqi.win/archives/1242
You have an array of positive integers a[1], a[2], …, a[n] and a set of bad prime numbers b1, b2, …, bm. The prime numbers that do not occur in the set b are considered good. The beauty of array a is the sum , where function f(s) is determined as follows:

f(1) = 0;
Let’s assume that p is the minimum prime divisor of s. If p is a good prime, then , otherwise .
You are allowed to perform an arbitrary (probably zero) number of operations to improve array a. The operation of improvement is the following sequence of actions:

Choose some number r (1 ≤ r ≤ n) and calculate the value g = GCD(a[1], a[2], …, a[r]).
Apply the assignments: , , …, .
What is the maximum beauty of the array you can get?

Input
The first line contains two integers n and m (1 ≤ n, m ≤ 5000) showing how many numbers are in the array and how many bad prime numbers there are.

The second line contains n space-separated integers a[1], a[2], …, a[n] (1 ≤ a[i] ≤ 109) — array a. The third line contains m space-separated integers b1, b2, …, bm (2 ≤ b1 < b2 < … < bm ≤ 109) — the set of bad prime numbers.

Output
Print a single integer — the answer to the problem.

Examples
Input
5 2
4 20 34 10 10
2 5
Output
-2
Input
4 5
2 4 8 16
3 5 7 11 17
Output
10
Note
Note that the answer to the problem can be negative.

The GCD(x1, x2, …, xk) is the maximum positive integer that divides each xi.

题意:给定一串数列可以进行针对前i个除以他们gcd的操作 次数不限

使得最后坏数的数量最少

这题可以贪心来考虑我们知道gcd的前缀肯定是随着长度的递升而递降或不变

那么也就是说我从后面做,删除的数前面一定也找得到

那么我首先先预处理个前缀和 是所有gcd的前缀和

然后我去检验这个这个数中是好数多还是坏数多,坏数多我们就除掉它,好数多就保留他

相当于是给gcd质因数分解了一下 查找他是不是坏数可以用二分

注意如果这个数不是质数也不是他的因数要跳过x

#include<cstdio>
#include<algorithm>
#define M 110000
#define N 5500
using namespace std;
inline char gc(){
    static char *S,*T,now[1<<16];
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (S==T) return EOF;}
    return *S++;
}
inline int read(){
    int x=0;char ch=gc();
    while(ch<'0'||ch>'9') ch=gc();
    while (ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=gc();}
    return x; 
}
int n,m,prime[M],not_prime[M],a[N],b[N],g[N],ans;
inline int gcd(int x,int y){if (y==0) return x;return gcd(y,x%y);}
int main(){
    //freopen("cf.in","r",stdin);
    n=read();m=read();int top=0;
    for (int i=2;i<=M-1;++i){
        if (!not_prime[i])prime[++top]=i;
        for (int j=1;prime[j]*i<=M;++j){
            not_prime[prime[j]*i]=true;
            if (i%prime[j]==0) break;
        }
    }
    for (int i=1;i<=n;++i) a[i]=read();
    for (int i=1;i<=m;++i) b[i]=read();sort(b+1,b+m+1);g[1]=a[1];
    for (int i=2;i<=n;++i) g[i]=gcd(a[i],g[i-1]);
    //for (int i=1;i<=n;++i) printf("%d ",g[i]);
    for (int i=n;i>=1;--i){
        int exist=0,not_exist=0,gg=g[i],g1=gg;
        for (int j=2;j*j<=gg;++j){
            if (not_prime[j]) continue;if (gg%j) continue;
            int pos=lower_bound(b+1,b+m+1,j)-b;
            while (gg%j==0){
                gg/=j;if (b[pos]==j) exist++;else not_exist++;
            }
        }
        if (gg>1) {
            int pos=lower_bound(b+1,b+m+1,gg)-b;
            if (b[pos]==gg) exist++;else not_exist++;
        }
        if (exist>=not_exist){
            for (int j=1;j<=i;++j) g[j]/=g1,a[j]/=g1;
        }
    }
    for (int i=1;i<=n;++i){
        int x=a[i];
        for (int j=2;j*j<=x;++j){
            if (not_prime[j]) continue;if (x%j) continue;
            int pos=lower_bound(b+1,b+m+1,j)-b;
            while (x%j==0){
                x/=j;if (b[pos]==j) ans--;else ans++;
            }
        }
        if (x>1) {
            int pos=lower_bound(b+1,b+m+1,x)-b;
            if (b[pos]==x) ans--;else ans++;
        }
    }
    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值