CF402D Upgrading Array
原题链接
先用素数筛筛下素数,然后考虑贪心去操作。
先求前缀\(GCD\)(求到\(GCD\)为\(1\)就不用再往下求了),得到数组\(G[i]\),然后从后往前扫,如果\(f(G[i]) < 0\),那么我们贪心地把\(i\)及之前的数全部除以\(G[i]\),当然前缀\(GCD\)数组同时也要除掉,然后重复上述操作,直到不能除为止。
计算\(f\)可以递归分解求解。
#include<cstdio>
using namespace std;
const int N = 5010;
const int M = 1e6;
int a[N], b[N], pr[M], G[N], l, m;
bool v[M + 10];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
int gcd(int x, int y)
{
if (!y)
return x;
return gcd(y, x % y);
}
bool fin(int x)
{
int l = 1, r = m, mid;
while (l <= r)
{
mid = (l + r) >> 1;
if (!(b[mid] ^ x))
return true;
b[mid] > x ? r = mid - 1 : l = mid + 1;
}
return false;
}
int js(int x)
{
if (!(x ^ 1))
return 0;
for (int i = 1; i <= l; i++)
{
if (pr[i] * pr[i] > x)
return fin(x) ? -1 : 1;
if (!(x % pr[i]))
return js(x / pr[i]) + (fin(pr[i]) ? -1 : 1);
}
}
int main()
{
int i, j, n, la;
long long s = 0;
n = re();
m = re();
for (i = 1; i <= n; i++)
a[i] = re();
for (i = 1; i <= m; i++)
b[i] = re();
v[0] = v[1] = 1;
for (i = 2; i <= M; i++)
{
if (!v[i])
pr[++l] = i;
for (j = 1; j <= l; j++)
{
if (i * pr[j] > M)
break;
v[i * pr[j]] = 1;
if (!(i % pr[j]))
break;
}
}
G[1] = a[1];
for (i = 2; i <= n; i++)
{
G[i] = gcd(G[i - 1], a[i]);
if (!(G[i] ^ 1))
break;
}
la = i - 1;
while(la > 0)
{
for (; js(G[la]) >= 0 && la > 0; la--);
if (la > 0)
for (i = 1; i <= la; i++)
{
a[i] /= G[la];
G[i] /= G[la];
}
}
for (i = 1; i <= n; i++)
s += js(a[i]);
printf("%lld", s);
return 0;
}
posted on 2018-10-30 19:18 Iowa_Battleship 阅读(115) 评论(0) 编辑 收藏 举报