Codeforces 1312 Div.2 筆記(1)
感想
感覺半夜打比賽很多時候腦子轉不過來,看懂了A-E的題面,剩下兩道題還需琢磨,C題起牀之後就想到做法然而賽場上沒有想出來;B題初步猜到結論然而沒有敢往上寫,只是交上了一個部分分。心態還是要調整,還有做題技巧還要提高。
題目
A Two Regular Polygons
解析
給定一個凸正邊形,問可不可以在裏面內嵌一個正邊形,使得的頂點全部都是的頂點,且的中心和的中心重合。
無非就是判斷的頂點去掉個之後剩下的頂點數是否還是的整數倍,3分鐘切。
代碼
#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;
}
bool ok(const int n, const int m)
{
if (n < 6)
return false;
int t = n - m;
if (t % m == 0)
return true;
return false;
}
int main(int argc, char **argv)
{
int T = nextInt();
while (T--)
{
int n = nextInt(), m = nextInt();
if (ok(n, m))
std::cout << "YES\n";
else
std::cout << "NO\n";
}
}
B Bogosort
解析
給定一個數組,若對於任何則稱這個數組爲好的。給出幾組數問如何調整才能調整成好數組。
一開始想到全排列挨個試,雖然最大複雜度但是感覺有機會,但不出所料TLE。後來想到是不是排序後倒序輸出就好,但沒敢試就結束了。最後查看他人AC代碼果然是這樣。感覺以後要大膽寫。
代碼
int main(int argc, char **argv)
{
int t = nextInt();
while (t--)
{
int n = nextInt();
for (int i = 1; i <= n; i++)
a[i] = nextInt();
std::sort(a + 1, a + n + 1);
for (int i = n; i >= 1; i--)
std::cout << a[i] << ' ';
std::cout << '\n';
}
return 0;
}
C Adding Powers
解析
給定數組全是0,給定一個數,你可以有若干操作步驟,第次將中的某一元素加上,給定數組,問若干次操作後可不可以變成。
初步想法是拆數,將每個拆成然後判斷是否有重複。後來不知爲何一直wa。早晨起來一改竟然過了。
代碼
#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;
}
const size_t _Siz = 1922;
ll a[_Siz];
int main(int argc, char **argv)
{
int T = nextInt();
while (T--)
{
int n = nextInt(), m = nextInt();
std::memset(a, 0, sizeof a);
for (int i = 1; i <= n; i++)
{
ll x = nextInt();
ll pos = 0;
while (x != 0) // 問題在這裏,wa版本這裏寫的是while (x % m)
{
a[++pos] += x % m;
x /= m;
}
}
bool flag = true;
for (int i = 1; i <= 100; i++)
if (a[i] > 1)
{
std::cout << "NO\n";
flag = false;
break;
}
if (flag)
std::cout << "YES\n";
}
}
D Count the Arrays
解析
給定個數的數組,對於任意整數都滿足,求有多少種方法使得數組中存在一個,使得前面的數嚴格遞增,後面的數嚴格遞減。
比賽時打眼一看推公式就跳過去了沒做。早上起來推了半天沒有思路,看別人的AC代碼發現是推組合數或者倍增。自己推了一遍,具體思路如下:
首先,不能在第一位和最後一位,所以從第2到n - 1每一位都可以放最大值,放上之後左右兩邊分別可以有和种放數的方法,然後最大值可以有 種情況,所以要乘。QED.
代碼
#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;
}
const size_t _Siz = 1992332;
ll kysumi(ll n, ll m, const ll p)
{
n = (n % p + p) % p;
ll ans = 1;
while (m)
{
if (m & 1)
ans = ans * n % p;
n = n * n % p;
m >>= 1;
}
return ans;
}
ll fac[_Siz] = { 0 };
const ll M = 998244353;
void Fact()
{
fac[0] = 1;
fac[1] = 1;
for (int i = 2; i <= _Siz - 4; i++)
fac[i] = i * fac[i - 1] % M;
}
ll C(const ll n, const ll m)
{
return fac[n] * kysumi(fac[n-m] * fac[m] % M, M - 2, M) % M;
}
int main(int argc, char **argv)
{
Fact();
// ll T = nextInt();
// while (T--)
// {
ll ans = 0;
ll n = nextInt(), m = nextInt();
for (int i = 2; i <= n - 1; i++)
ans = (ans + C(m, n - 1) * C(n - 2, i - 2) % M * (n - i) % M) % M;
std::cout << ans << std::endl;
// }
return 0;
}
E Array Shrinking
解析
給定一個數組,如果這個數組裏有兩個數和相同,那麼可以把這個兩個數替換成一個數。問執行若干遍操作之後數組最短是多少。
比賽現場的時候就純暴力模擬這個過程,不出所料wa了第5個點。感覺是dp,然而沒有推出正確的方程。早上起來列了個表之後推出做法了:
用f[i, j]代表起點爲i,終點爲j的子區間,如果可以合併的話該值爲合併後的值,否則爲0。枚舉長度和左節點i,如果可以合併的話取最小值dp[i]。
代碼
#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;
}
const size_t _Siz = 622;
ll a[_Siz] = { 0 }, b[_Siz] = { 0 }, n, m;
ll f[_Siz][_Siz], dp[_Siz];
int main(int argc, char **argv)
{
n = nextInt();
for (int i = 1; i <= n; i++)
{
a[i] = nextInt();
f[i][i] = a[i];
}
for (int len = 2; len <= n; len++)
for (int l = 1; l <= n - len + 1; l++)
{
int r = l + len - 1;
for (int k = l; k <= r; k++)
{
if (f[l][k] && f[k + 1][r] && f[l][k] == f[k + 1][r])
f[l][r] = f[l][k] + 1;
}
}
std::memset(dp, 0x3f, sizeof dp);
dp[0] = 0;
for (int i = 1; i <= n; i++)
for (int j = 0; j < i; j++)
if (f[j + 1][i])
dp[i] = std::min(dp[i], dp[j] + 1);
std::cout << dp[n] << std::endl;
return 0;
}