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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章