好像没有什么要说的,主要是两个数组的数据范围太大,要做好优化,避免因子的重复计算。
预处理:
首先计算出 a[] 初始时的 Max = sigma f(a[i]) (1 <= i <= n).
然后,对于 a[i] ,计算出所有的 gcd[i] ,可以从左边开始递推,时间复杂度o(n).
从gcd[n] 开始往左遍历,若f( gcd[ i ] ) < 0,Max -= i*f ( gcd[i] ),site = i。
继续枚举 i ,若 f(gcd[i] / gcd[site]) < 0,则 Max -= i*f( gcd[i] / gcd[site]),site = i , 直到 i < 1;
代码又写的很长 . . . . . .
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>
#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long int
#define ULL unsigned long long int
#define _LL __int64
#define _INF 0x3f3f3f3f
#define INF 40000000
#define Mod 1000000009
using namespace std;
int Top_Prime;
int prime[100000];
bool mark[100000];
int pg[5010];
int a[5010],b[5010];
int n,m;
struct N
{
int s,f;
N *l,*r;
}*root;
N *creat()
{
N *p = (N *)malloc(sizeof(N));
p->l = NULL,p->r = NULL;
return p;
}
void Insert(N *&root ,int s,int f)
{
if(root == NULL)
{
root = creat();
root->s = s;
root->f = f;
return ;
}
if(s < root->s)
{
Insert(root->l,s,f);
}
else
{
Insert(root->r,s,f);
}
}
bool Is_good(int p)
{
int s = 1,e = m;
int mid = (s+e)>>1;
while(s < e)
{
if(b[mid] == p)
return false;
if(p < b[mid])
e = mid-1;
else
s = mid+1;
mid = (s+e)>>1;
}
if(p == b[(s+e)>>1])
return false;
return true;
}
int Query(N *root,int s)
{
if(root == NULL)
return -1;
if(root->s == s)
return root->f;
if(s < root->s)
return Query(root->l,s);
return Query(root->r,s);
}
int Cal_F(int a)
{
if(a == 1)
return 0;
int temp = Query(root,a);
if(temp != -1)
return temp;
int i;
for(i = 0;i < Top_Prime; ++i)
{
if(a%prime[i] == 0)
break;
}
int r;
if(i == Top_Prime)
r = a;
else
r = prime[i];
temp = Cal_F(a/r) + (Is_good(r) == true ? 1 : -1);
Insert(root,a,temp);
return temp;
}
int gcd(int a,int b)
{
return (b == 0 ? a : gcd(b,a%b));
}
int main()
{
memset(mark,false,sizeof(mark));
int i,j;
for(i = 2;i <= 100000; ++i)
{
if(mark[i] == false)
{
for(j = i+i;j <= 100000; j += i)
{
mark[j] = true;
}
}
}
Top_Prime = 0;
for(i = 2;i <= 100000; ++i)
{
if(mark[i] == false)
{
prime[Top_Prime++] = i;
}
}
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]);
}
sort(b+1,b+1+m);
int Max = 0;
for(i = 1;i <= n; ++i)
{
Max += Cal_F(a[i]);
}
pg[1] = a[1];
for(i = 2;i <= n; ++i)
{
pg[i] = gcd(pg[i-1],a[i]);
}
int l;
for(i = n;i >= 1; --i)
{
int tt = Cal_F(pg[i]);
if(tt < 0)
{
Max -= i*tt;
l = i;
break;
}
}
for(--i ; i >= 1; --i)
{
int tt = Cal_F(pg[i]/pg[l]);
if(tt < 0)
{
Max -= i*tt;
l = i;
}
}
printf("%d\n",Max);
return 0;
}