1. 程式人生 > 其它 >CodeTON Round 1 (Div. 1 + Div. 2, Rated, Prizes!)

CodeTON Round 1 (Div. 1 + Div. 2, Rated, Prizes!)

CodeTON Round 1 (Div. 1 + Div. 2, Rated, Prizes!)

A. Good Pairs

思路:我們可以根據幾何意義轉化下問題:在數軸上存在一些點,能否找到兩個點滿足其餘的點到這兩個點的距離等於這兩個點的距離。答案顯然是陣列中最大和最小的元素下標。

void solve()
{
	int n;
	cin >> n;
	for(int i = 1; i <= n; i ++ ){
		cin >> a[i];
	}
	cout << max_element(a + 1, a + 1 + n) - a << " " << min_element(a + 1, a + 1 + n) - a << endl;
}

B. Subtract Operation

思路:由於需要把陣列刪到只剩下最後一個元素,那麼在最後一步操作的前的兩個數差值一定為\(k\),那麼,這兩個數之前減去的所有數的和是一樣的,所以只要滿足這兩個數一開始的差值是\(k\)即可。

void solve()
{
	cin >> n >> k;
	map<int,int>mp;
	for(int i = 1; i <= n; i ++ ){
		cin >> a[i];
		mp[a[i]] ++;
	}
	for(int i = 1; i <= n; i ++ ){
		if(mp[a[i] - k]){
			cout << "Yes" << endl;
			return;
		}
	}
	cout << "No" << endl;
	return;
}

C. Make Equal With Mod

如果原陣列中沒有\(1\),那麼我們可以不斷 \(mod\)陣列中大的數把原陣列都變成\(0\)

如果陣列中有\(1\),我們要使陣列中所有的值都相等,只能把陣列中所有的元素都變成\(1\),那麼我們就需要\(mod\)上比原來的數小\(1\)的數,如果出現差值為1的兩個元素,就無法實現把前者變成\(1\)

綜上:陣列中有\(1\),且出現連續的元素,就是不合法,其餘合法。

void solve()
{
	cin >> n;
	bool ok1 = false;
	map<int,int>mp;
	for(int i = 1; i <= n; i ++ ){
		cin >> a[i];
		mp[a[i]] ++;
		if(a[i] == 1) ok1 = true;
	}
	bool ok2 = false;
	for(int i = 1; i <= n; i ++ ){
		if(mp[a[i] - 1] || mp[a[i] + 1]){
			ok2 = true;
		}
	}
	if(ok1 && ok2){
		cout << "No" << endl;
		return;
	}
	cout << "Yes" << endl;
 
}

D. K-good

思路:把題目寫成數學表示式:

\[n = x* k + \frac{(k - 1) * k }{2}, x \geq 0, k\geq 2 \]

轉化為一元二次方程方程,解出來\(k\),並取正的解

\[k =\frac{1 - 2 * x + \sqrt{(2 * x - 1)^2 + 8 * n}}{2} \]

要保證\(k\)為整數,那麼分子的根號算出來一定是個奇數,因為分子前面一部分是奇數,我們設:

\[\sqrt{(2 * x - 1)^2 + 8 * n} = 2 * p + 1 \]

左右平方然後進行平方差公式得到:

\[(p - x + 1) * (p + x) = 2 * n \]

我們發現等式左邊是\(1\)個奇數\(1\)個偶數,奇數就是\(n\)的奇數因子,我們可以預處理出來,我們先設\(n\)的奇數因子為\(a\),有兩種情況:

\[p - x + 1 = a, p + x = \frac{2 * n}{a} \]

\[p + x = a, p - x + 1 = \frac{2 * n}{a} \]

由於\(n\)\(a\)是已知的,我們可以解出\(p\)\(x\)。然後帶入上面\(k\)的表示式,算出有\(k\)有兩個結果:

\[k = a或者k = \frac{2 * n}{a} \]

我們可以發現,如果\(n\)\(2\)的次冪,那麼\(k = 1, 或者 k = 2 * n\)\(k\)不合法。

由於第一個式子中\(x \geq 0\),我們可以對這個式子進行放縮:

\[n \geq \frac{(k - 1) * k }{2}, x \geq 0, k\geq 2 \]

為了更加容易滿足這個式子,\(k\)應該越小越好,所以,\(k\)取兩個值的最小值即可。

void solve()
{
	cin >> n;
	if(n % 2 == 1){
		cout << 2 << endl;
		return;
	}
	LL qwq = n * 2;
	while(n % 2 == 0)  n /= 2;
	if(n == 1){
		cout << "-1" << endl;
		return;
	}
	cout << min(n, qwq / n) << endl;
}

E. Equal Tree Sums

思路:我們先統計出所有結點的度數,然後對樹進行黑白染色,使得刪除任意一個結點,剩餘的連通塊的權值總和為\(-1\)

void dfs(int x, int u){
	if(u == 1) ans[x] = du[x];
	else ans[x] = -du[x];
	for(auto it : v[x]){
		// debug(it);
		if(!ans[it]){
			dfs(it, u ^ 1);
		}
	}
} 
 
void solve()
{
	cin >> n;
	for(int i = 1; i <= n; i ++ ){
		du[i] = ans[i] = 0;
		v[i].clear();
	}
	for(int i = 1; i <= n - 1; i ++ ){
		int a, b;
		cin >> a >> b;
		du[a] ++;
		du[b] ++;
		v[a].pb(b), v[b].pb(a);
	}
	dfs(1, 1);
	for(int i = 1; i <= n; i ++ ){
		cout << ans[i] << ' ';
	}
	cout << endl;
}