一名苦逼的OIer,想成为ACMer

Iowa_Battleship

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编辑  收藏  举报

导航