Codeforces Round #601

B. Send Boxes to Alice (Easy/Hard Version) (1s 256Mb)

题目大意

 (100 / 1e6)n \left(1 \leq n \leq 1e5/1e6 \right ) 个排列好的盒子,每个盒子里有 a_i\left(0 \leq a_i \leq 1/1e6 \right ) 块巧克力。可以花费1秒的时间将一块巧克力从一个盒子移动到左右相邻的盒子,问最少可以用多少秒,使得每个盒子里的巧克力数都可以被k整除。其中k是大于2的任意数。

分析

Easy:每个盒子要么有一块要么没有。对于specific k,将相邻的k个1整合所花费时间最少。可以暴力枚举所有sum(巧克力总数)的因数为k求解,取答案最小。小于1e5的数最多有128个因子。sum == 1时输出-1。O(128*n)。

Hard:

使用前缀和,移动等价于某个 s_i 加一或者减一。既然最后每个 a_i 可以被k整除(不同于Easy,可以是k的倍数),显然最终情况等价于每个 s_i 也可以被k整除。

对于每一个 s_i ,使用 min(s_i\%k, k - s_i\%) 秒(贪心)使合法,由于 s_i \leq s_{i+1},所以不会出现逆序的非法情况。可以O(n)求解一个k的答案。

观察可知答案对应的k一定是素数(合数k的情况被其素因子包括),对于1e12,最多有12个不同的素因子,唯一分解即可。

代码

const int maxn = 1e6+10;
int n;
ll a[maxn], s[maxn];

ll work(ll k)
{
	ll res = 0;
	for(int i = 1; i < n; i++) res += min(s[i]%k, k-s[i]%k);
	return res;
}

int main()
{
	n = read();
	for(int i = 1; i <= n; i++) a[i] = read(), s[i] = s[i-1]+a[i];
	if(s[n] == 1)
	{
		printf("-1\n"); return 0;
	}
	ll ans = 9e18, tmp = 2, num = s[n];
	while(tmp * tmp <= num)
	{
		if(num%tmp == 0)
		{
			ans = min(ans, work(tmp));
			while(num%tmp == 0) num /= tmp;
		}
		tmp++;
	}
	if(num > 1) ans = min(ans, work(num));
	printf("%I64d\n", ans);
	return 0;
}

C. League of Leesins (2s 256Mb)

题目大意

对于每个排列p有n-2 \left(5 \leq n \leq 1e5 \right ) 个q,q_i = (p_i, p_{i+1}, p_{i+2})。给出一组q,构造一个p。

分析

模拟题,找到只出现一次的p,一定是开头,找到含这个p的q里只出现两次的p,一定是开头后。使用这个q去递推下一个q,直到构成所有数列。

代码

const int maxn = 2e5+10;
struct Node
{
	int fi, se, th;
} a[maxn];
vector<int> b[maxn];
int vis[maxn], visb[maxn], n, sum[maxn];
//cnt构建了几个 sta当前p第一个 fol第二个 nt第三个 id是q的下标  
void dfs(int cnt, int sta, int fol, int nt, int id)  
{
	printf("%d ", nt); //输出 
	if(cnt == n-2) return;
	vis[id] = 1; visb[nt] = 1;
	int nid;//下一个q的id 
	if(cnt == 1) nid = b[fol][0] == id ? b[fol][1] : b[fol][0];// 第一个q无前一个q, 特判 
	else nid = vis[b[fol][0]] ? (vis[b[fol][1]] ? b[fol][2]:b[fol][1]):b[fol][0];//有nt的q里还没用过的 
	int nnt = visb[a[nid].fi] ? (visb[a[nid].se] ? a[nid].th : a[nid].se) : a[nid].fi;
	dfs(cnt+1, fol, nt, nnt, nid);
}

int main()
{
	n = read();
	for(int i = 1, u, v, w; i <= n-2; i++)
	{
		u = read(), v = read(), w = read();
		a[i] = (Node){u, v, w};
		b[u].push_back(i);
		b[v].push_back(i);
		b[w].push_back(i);
		sum[u]++, sum[v]++, sum[w]++;
	}
	int sta, fol, nt;
	for(int i = 1; i <= n; i++) if(sum[i] == 1) { sta = i; break; }
	if(sum[a[b[sta][0]].se] == 2) 
	{
		fol = a[b[sta][0]].se;
		if(sum[a[b[sta][0]].fi]== 3) nt = a[b[sta][0]].fi;
		else nt = a[b[sta][0]].th;
	}
	else if(sum[a[b[sta][0]].fi] == 2) 
	{
		fol = a[b[sta][0]].fi;
		if(sum[a[b[sta][0]].se]== 3) nt = a[b[sta][0]].se;
		else nt = a[b[sta][0]].th;
	}
	else if(sum[a[b[sta][0]].th] == 2) 
	{
		fol = a[b[sta][0]].th;
		if(sum[a[b[sta][0]].fi]== 3) nt = a[b[sta][0]].fi;
		else nt = a[b[sta][0]].se;
	}
	printf("%d %d ", sta, fol);
	visb[sta] = visb[fol] = 1;
	dfs(1, sta, fol, nt, b[sta][0]);
	
	return 0;
}

B. Fridge Lockers (1s 256Mb)

题目大意

花里胡哨。图,n个点,每个点有ai,要求建m条边,使得满足每个点都和至少两个不同的点相连,且代价最小。

分析

Mike翻车了hhh

https://codeforces.com/blog/entry/71562?#comment-559266

发布了18 篇原创文章 · 获赞 0 · 访问量 1137

猜你喜欢

转载自blog.csdn.net/DWAE86/article/details/103245897