Codeforces 1325 Div.2 筆記

Codeforces 1325 Div.2 筆記

感想

又是掉分的一場。因爲記錯了時間而遲到了一個小時,只做出了AB題。感覺這次的思維量太大了,感覺這次出得比較好的是A題和C題(因爲D題當時沒看)。還有要求穩,B題提交了5次,根本沒有分數可言。以後要注意。掉到1300Rating了,跟1900感覺距離越來越大了。

題目

A EhAb AnD gCd

解析

給定一個整數nn,要求出兩個整數x,yx, y,使得Gcd(x,y)+Lcm(x,y)=nGcd(x, y) + Lcm(x, y) = n

乍一看數據比較大,1n1091 \le n \le 10^9,套Gcd和Lcm的話絕對超時,但仔細想了一下,Gcd(1, n - 1)一定是1,Lcm(1, n - 1)一定是n - 1,加起來就好了。

代碼

#include <bits/stdc++.h>

typedef long long ll;

ll nextInt()
{
	ll num = 0;
	char c = 0;
	bool flag = false;
	while ((c = std::getchar()) == ' ' || c == '\r' || c == '\t' || c == '\n');
	if (c == '-')
		flag = true;
	else
		num = c - 48;
	while (std::isdigit(c = std::getchar()))
		num = num * 10 + c - 48;
	return (flag ? -1 : 1) * num;
}

int main(int argc, char **argv)
{
	int t = nextInt();
	while (t--)
	{
		ll n = nextInt();
		std::cout << 1 << ' ' << n - 1 << std::endl;
	}
}

B CopyCopyCopyCopyCopy

解析

給定一組數AiA_i,由nn個數組成。求出將該數組複製nn次後,形成的新數組中的最長嚴格上升子序列。

這題我交了5遍。第一次用了n2n^2的LIS,超時。第二次用了nlog2nn log_2 n的LIS,超時。第三次我發現,既然是複製nn次,那麼沒必要一個個求啊,首位看只要能構成上升就都可以取到。於是交了個map判重,超時。後來改成了set輸出size(),玄學超時。改了一下將set定義在外面,交上去就過了。感覺要想好再往上交。

代碼

#include <bits/stdc++.h>

typedef long long ll;

ll nextInt()
{
	ll num = 0;
	char c = 0;
	bool flag = false;
	while ((c = std::getchar()) == ' ' || c == '\r' || c == '\t' || c == '\n');
	if (c == '-')
		flag = true;
	else
		num = c - 48;
	while (std::isdigit(c = std::getchar()))
		num = num * 10 + c - 48;
	return (flag ? -1 : 1) * num;
}

std::set<int> s;

int main(int argc, char **argv)
{
	int T = nextInt();
	while (T--)
	{
		s.clear();
		ll n = nextInt();
		for (int i = 1; i <= n; i++)
		{
			ll x = nextInt();
			s.insert(x);
		}
		std::cout << s.size() << std::endl;
	}
}

C Ehab and Path-etic MEXs

解析

給定一顆有nn個節點n1n-1條邊的樹,要求在所有邊上標上0,1,2,,n20,1,2,\ldots , n-2,定義MEX(u,v)MEX(u,v)爲該樹上,u到v的簡單路徑要經過的邊除外,樹上所有邊的值中的最小值,使得對於任意的u,vu,vMEXuvMEX(u,v)的最大值儘可能地小。

這題光讀題就讀了40min,最後也是沒調出來。第二天想了一下發現,統計一個訪問次數,次數是1的點即爲葉子節點,讓每一個葉子節點所經過的路徑變成最小的距離即可。

代碼

#include <bits/stdc++.h>

typedef long long ll;

ll nextInt()
{
	ll num = 0;
	char c = 0;
	bool flag = false;
	while ((c = std::getchar()) == ' ' || c == '\r' || c == '\t' || c == '\n');
	if (c == '-')
		flag = true;
	else
		num = c - 48;
	while (std::isdigit(c = std::getchar()))
		num = num * 10 + c - 48;
	return (flag ? -1 : 1) * num;
}

size_t _Siz = 109231;

int main(int argc, char **argv)
{
	int vis[_Siz] = { 0 }, ans[_Siz] = { 0 }, pos[_Siz] = { 0 };
	std::memset(ans, 0xff, sizeof ans);
	int n = nextInt();
	for (int i = 1; i < n; i++)
	{
		int x = nextInt(), y = nextInt();
		vis[x]++;
		vis[y]++;
		pos[x] = i, pos[y] = i;
	}
	int tot = 0;
	for (int i = 1; i <= n; i++)
		if (vis[i] == 1)
			ans[pos[i]] = tot++;
	for (int i = n - 1; i >= 1; i--)
		if (ans[i] == -1)
			ans[i] = tot++;
	for (int i = 1; i < n; i++)
	{
		if (ans[i] == n - 1)
			ans[i] = 0;
		std::cout << ans[i] << '\n';
	}
	return 0;
}

D Ehab the Xorcist

解析

構造一個儘可能短的長度爲nn的數組,使得該數組所有元素的和爲給定值vv,所有元素異或和爲給定值uu

昨晚上牀之後想到,要先判斷是否有解。因爲如果v<uv < u的話是一定無解的。

其次,若異或和的個位爲1,則該數組中,個位爲1的個數必爲奇數,則和的個位也應爲1。同理,若異或和的個位爲0,則和的個位也應爲0。

所以,當且僅當vuv\ge u(vu)2(v-u)|2的情況下,u,vu, v有解。

顯然,在u,vu, v有解的情況下,u,(vu)/2,(vu)/2{u,(v-u)/2,(v-u)/2}是一種始終有解的構造,所以我們只需要考慮特判n<3n<3的情況。

n=0:在u=v=0的情況下有解。

n=1:在u=v的情況下有解。

n=2:在{(v+u)/2、(v-u)/2}滿足條件的情況下成立。

代碼

#include <bits/stdc++.h>

typedef long long ll;

ll nextInt()
{
	ll num = 0;
	char c = 0;
	bool flag = false;
	while ((c = std::getchar()) == ' ' || c == '\r' || c == '\t' || c == '\n');
	if (c == '-')
		flag = true;
	else
		num = c - 48;
	while (std::isdigit(c = std::getchar()))
		num = num * 10 + c - 48;
	return (flag ? -1 : 1) * num;
}

ll n, m;
int main(int argc, char **argv) 
{
	n = nextInt();
	m = nextInt();
    if (n > m || (m - n) % 2 != 0)
	{
        puts("-1");
        return 0;
    } 
	else if (n == m && n == 0) 
	{
        puts ("0");
    } 
	else if (n == m) 
	{
        std::cout << 1 << '\n' << n << '\n';
    } 
	else 
	{
        long long x = (n + m) / 2, y = n;
        long long a = x, b = x - y;
        if ((a + b) == m && (a ^ b) == n)
            std::cout << 2 << '\n' << a << ' ' << b << '\n';
        else
            std::cout << 3 << '\n' << n << ' '  << (m - n) / 2 << ' ' <<  (m - n) / 2);
        return 0;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章