题目链接:http://codeforces.com/contest/402/problem/D
题目意思:求最大数组前缀式
The beauty of array a is the sum 求这个 sum 的最大值
f(s) 是递归定义的 描述如下:
- f(1) = 0;
- Let's assume that p is the minimum prime divisor of s. If p is a good prime, then
, otherwise
.
你可以对数组进行 0 次或多次操作,使你能获得更大的值。操作方式如下:
- Choose some number r (1 ≤ r ≤ n) and calculate the value g = GCD(a[1], a[2], ..., a[r]).
- Apply the assignments:
,
, ...,
.
1、计算出还没处理时候的值 maxp
2、因为是处理前缀式,故应该从最后一个值开始处理,建设当前处理的数的位置为 i ,则考察 f(gcd(i)) ,如果 f(gcd(i)) < 0 ,则应去掉该 公约数,并记录下当前位置,在处理下一个最大公约数的时候,应该前面已经处理过 i 位置的公约数, 故应该考察 f(gcd(j)/gcd(i)) 。
注: 可以用素数筛生成一个素数表,1e9 最小的质因数不会超过1e5 。
代码:
#include <stdio.h>
#include <string.h>
#include <math.h>
#define MAXN 5005
#define MAXB 100100
#define MAXP 10010
int m, n, primes[MAXP], prime[MAXB], gDP[MAXN], a[MAXN], b[MAXN];
int GCD(int m, int n){
if(m < n)
return GCD(n, m);
while(n){
int t = m;
m = n;
n = t % m;
}
return m;
}
void dpGCD(int n){
int r;
for(r = 1; r <= n; ++r)
gDP[r] = GCD(a[r], gDP[r-1]);
gDP[0] = 1;
}
void primeFactor(){
int i, j, x = 0;
prime[0] = 1; prime[1] = 1;
for(i = 4; i < MAXB; i+=2)
prime[i] = 1;
for(j = 3; j < MAXB; j+=2){
if(!prime[j]){
for(i = 2*j; i < MAXB; i+=j)
prime[i] = 1;
}
}
for(i = 0, j = 1; i < MAXB; ++i){
if(!prime[i])
primes[j++] = i;
}
}
int Factor(int n){
int j;
for(j = 1; primes[j]; ++j)
if(n % primes[j] == 0)
return primes[j];
return n;
}
int isBadPrime(int p, int m){
int left, mid, right;
left = 1; right = m;
while(left <= right){
mid = (left + right)/2;
if(p == b[mid])
return 1;
else if(p > b[mid])
left = mid + 1;
else
right = mid - 1;
}
return 0;
}
int f(int n){
int i, p, c = 0;
for(i = n; i > 1; i /= p){
p = Factor(i);
if(isBadPrime(p, m))
--c;
else
++c;
}
return c;
}
int main(){
int i, j, p, r, maxp, maxb;
scanf("%d%d", &n, &m);
for(i = 1; i <= n; ++i)
scanf("%d", a+i);
for(i = 1; i <= m; ++i)
scanf("%d", b+i);
dpGCD(n); primeFactor(); maxp = 0;
for(i = 1; i <= n; ++i){
maxp += f(a[i]);
}
int l = 0;
for(i = n; i >= 1; --i){
int tmp = f(gDP[i]/gDP[l]);
if(tmp < 0){
maxp -= i*tmp;
l = i;
}
}
printf("%d\n", maxp);
return 0;
}