题目链接: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 " , ans); return 0; }