题目链接:http://codeforces.com/contest/402/problem/D
题意:给出一个a串和素数串b 。f(1) = 0; p为s的最小素因子如果p不属于b
, 否则
.
a串还可以进行这样的操作找一个r使得(1<=r<=n)g=gcd(a[1],a[2]......a[r]),然后再是a[1~r]/g。
题解:其实f的求和可以理解为num1(好的素因子)-num2(不好的素因子)。
然后就是对a操作的理解,a怎么样才需要进行这样的操作呢?只要g中不好的素因子大于好的素因子那么,
删掉这样的g就能增加f的总和。还有求除最小素因数的方法
for(int j = 2 ; j * j <= x ; j++) {//这个是快速的求法,为什么这么求可以自行理解
if(!prime[j])//prime表示是否是素数与处理一下
continue;
if(x % j)
continue;
bool flag = mmp[j];//定义map的mmp来判断j是否是坏素因数
while(x % j == 0) {
x /= j;
if(flag)
ans--;
else
ans++;
}
}
if(x > 1) {
if(mmp[x])
ans--;
else
ans++;
}
#include <iostream>
#include <cmath>
#include <cstdio>
#include <map>
#define inf 0X3f3f3f3f
using namespace std;
const int M = 1e5 + 10;
int a[5010] , b[5010];
int prime[M];
map<int , bool>mmp;
void IsPrime(){
prime[0] = prime[1] = 0;
prime[2] = 1;
for(int i = 3 ; i < M ; i++)
prime[i] = i % 2 == 0 ? 0 : 1;
int t = (int)sqrt(M * 1.0);
for(int i = 3 ; i <= t ; i++)
if(prime[i])
for(int j = i * i ; j < M ; j += 2 * i)
prime[j] = 0;
}
int gcd(int x , int y) {
return (y > 0) ? gcd(y , x % y) : x;
}
int main() {
int n , m;
scanf("%d%d" , &n , &m);
mmp.clear();
IsPrime();
for(int i = 0 ; i < n ; i++) {
scanf("%d" , &a[i]);
}
for(int i = 0 ; i < m ; i++) {
scanf("%d" , &b[i]);
mmp[b[i]] = true;
}
for(int i = n - 1 ; i >= 0 ; i--) {
int x = 0;
for(int j = 0 ; j <= i ; j++) {
x = gcd(x , a[j]);
}
int bad = 0 , good = 0;
int xx = x;
for(int l = 2 ; l * l <= x ; l++) {
if(!prime[l])
continue;
if(x % l)
continue;
bool flag = mmp[l];
while(x % l == 0) {
x /= l;
if(flag)
bad++;
else
good++;
}
}
if(x > 1) {
if(mmp[x])
bad++;
else
good++;
}
if(bad > good) {
for(int j = 0 ; j <= i ; j++) {
a[j] /= xx;
}
}
}
int ans = 0;
for(int i = 0 ; i < n ; i++) {
int x = a[i];
for(int j = 2 ; j * j <= x ; j++) {
if(!prime[j])
continue;
if(x % j)
continue;
bool flag = mmp[j];
while(x % j == 0) {
x /= j;
if(flag)
ans--;
else
ans++;
}
}
if(x > 1) {
if(mmp[x])
ans--;
else
ans++;
}
}
printf("%d\n" , ans);
return 0;
}