Codeforces 1325 Div.2 筆記
感想
又是掉分的一場。因爲記錯了時間而遲到了一個小時,只做出了AB題。感覺這次的思維量太大了,感覺這次出得比較好的是A題和C題(因爲D題當時沒看)。還有要求穩,B題提交了5次,根本沒有分數可言。以後要注意。掉到1300Rating了,跟1900感覺距離越來越大了。
題目
A EhAb AnD gCd
解析
給定一個整數,要求出兩個整數,使得。
乍一看數據比較大,,套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
解析
給定一組數,由個數組成。求出將該數組複製次後,形成的新數組中的最長嚴格上升子序列。
這題我交了5遍。第一次用了的LIS,超時。第二次用了的LIS,超時。第三次我發現,既然是複製次,那麼沒必要一個個求啊,首位看只要能構成上升就都可以取到。於是交了個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
解析
給定一顆有個節點條邊的樹,要求在所有邊上標上,定義爲該樹上,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
解析
構造一個儘可能短的長度爲的數組,使得該數組所有元素的和爲給定值,所有元素異或和爲給定值。
昨晚上牀之後想到,要先判斷是否有解。因爲如果的話是一定無解的。
其次,若異或和的個位爲1,則該數組中,個位爲1的個數必爲奇數,則和的個位也應爲1。同理,若異或和的個位爲0,則和的個位也應爲0。
所以,當且僅當且的情況下,有解。
顯然,在有解的情況下,是一種始終有解的構造,所以我們只需要考慮特判的情況。
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;
}