牛客练习赛131(A~C)
小H学语文
排序 枚举 贪心
思路
排序,枚举哪一个最短,注意同时记录下标
神奇的代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int maxn = 2e5 + 5;
const int inf = 0x7f7f7f7f;
struct Node
{
int len;
int id;
} nums[maxn];
bool cmp(Node a, Node b)
{
if (a.len != b.len)
{
return a.len < b.len;
}
else
{
return a.id < b.id;
}
}
void solve()
{
int n = 0;
std::cin >> n;
int pos = 0;
for (int i = 1; i <= n; i++)
{
std::cin >> nums[i].len;
nums[i].id = i;
}
std::sort(nums + 1, nums + 1 + n, cmp);
int mx = 0;
for (int i = 1; i <= n; i++)
{
int tmp = nums[i].len * (n - i + 1) * (n - i + 1);
if (tmp > mx)
{
mx = tmp;
pos = i;
}
}
std::cout << n - pos + 1 << endl;
std::vector<int> t;
for (int i = pos; i <= n; i++)
{
t.push_back(nums[i].id);
}
std::sort(t.begin(), t.end());
for (auto x : t)
{
std::cout << x << " ";
}
}
小H学数学
dp 暴力
思路
范围较小,可以把每个人单独看
\(dpp[i][j]\)表示前\(i\)个人能表示\(j\)的方法数
因为有负数,要设置一个偏移量\(N = 10^3\)
然后分成两次去枚举,一次是用两只手表示一个数,一次是用两只手表示两个数
代码
神奇的代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int maxn = 2e5 + 5;
const int inf = 0x7f7f7f7f;
const int mod = 1e9 + 7;
// dp[i][j] 第i步达到j的方案数
int c[11] = {0, 9, 8, 7, 6, 5, 6, 5, 4, 3, 2};
int dp[110][2020];
const int N = 1e3;
void add(int x, int y, int w)
{
if (y + w >= 0 && y + w <= 2 * N)
{
dp[x][y] += dp[x - 1][y + w], dp[x][y] %= mod;
}
}
void solve()
{
int x = 0, y = 0;
std::cin >> x >> y;
dp[0][N] = 1;
for (int i = 1; i <= y + 1; i++)
{
for (int j = 0; j <= 2 * N; j++)
{
for (int k = 1; k <= 10; k++)
{
add(i, j, k);
add(i, j, -k);
}
for (int k1 = 1; k1 <= 5; k1++)
{
for (int k2 = 1; k2 <= 5; k2++)
{
add(i, j, k1 + k2);
add(i, j, k1 - k2);
add(i, j, -k1 - k2);
add(i, j, -k1 + k2);
}
}
}
}
std::cout << dp[y + 1][x + N] << endl;
}
赛时想法 把一个人能表达的数的方法数求出来
int c[11] = {10, 9, 8, 7, 6, 5, 6, 5, 4, 3, 2};
这个时候\(0\)也要算,因为两只手能把\(0\)表示出来
神奇的代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int maxn = 2e5 + 5;
const int inf = 0x7f7f7f7f;
const int mod = 1e9 + 7;
// dp[i][j] 第i步达到j的方案数
int c[11] = {10, 9, 8, 7, 6, 5, 6, 5, 4, 3, 2};
int dp[110][2020];
const int N = 1e3;
void solve()
{
int x = 0, y = 0;
std::cin >> x >> y;
dp[0][1000] = 1;
for (int i = 1; i <= y + 1; i++)
{
for (int j = 0; j <= 2 * N; j++)
{
for (int k = 0; k <= 10; k++)
{
dp[i][j - k] += (dp[i - 1][j] * c[k] % mod) % mod; dp[i][j - k] %= mod;
if (k == 0) continue;
dp[i][j + k] += (dp[i - 1][j] * c[k] % mod) % mod; dp[i][j - k] %= mod;
}
}
}
std::cout << dp[y + 1][x + 1000] % mod << endl;
}
小H学生物
思维 位运算 \(dfs\)
思路
\(D_{i, j}\) = \(D_{1, i}\oplus D_{1, j}\)
\(\bigoplus\limits_{i = 1}^{m - 2}\bigoplus\limits_{j = i + 2}^{m}D_{a_i, a_j}\)就可以转化为\(\bigoplus\limits_{i = 1}^{m - 2}\bigoplus\limits_{j = i + 2}^{m}D_{1, a_i}\oplus D_{1, a_j}\)
我们只需要计算各个数在表达式中出现的次数就好了
瞪眼法?找规律就是 \(a_1和a_m都出现了m - 2次,其他出现了m-3次\)
那么有这样两种情况
-
\(m\)为奇数,那就只剩下了\(a_1和a_m\)
-
\(m\)为偶数,那就只剩下了其他的
维护祖先到每一个物种的变异程度
时间复杂度\(O(n)\)
代码
神奇的代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int maxn = 1e5 + 5;
const int inf = 0x7f7f7f7f;
std::vector<int> tree[maxn];
std::string d[maxn];
int n = 0, m = 0, L = 0;
std::string sxor(std::string s, std::string t)
{
std::string res(L, '0');
for (int i = 0; i < L; i++)
{
if (s[i] == t[i])
{
res[i] = '0';
}
else
{
res[i] = '1';
}
}
return res;
}
void dfs(int root)
{
for (int i = 0; i < tree[root].size(); i++)
{
int t = tree[root][i];
d[t] = sxor(d[t], d[root]);
dfs(t);
}
}
void solve()
{
std::cin >> n >> m >> L;
int u = 0, v = 0;
for (int i = 1; i <= n - 1; i++)
{
std::cin >> u >> v >> d[v];
tree[u].push_back(v);
}
int tmp = 0;
d[1] = std::string (L, '0');
std::vector<int> id(m + 1, 0);
for (int i = 1; i <= m; i++)
{
std::cin >> id[i];
}
dfs(1);
if (m & 1)
{
std::cout << sxor(d[id[1]], d[id[m]]) << endl;
}
else
{
std::string ans (L, '0');
for (int i = 2; i <= m - 1; i++)
{
ans = sxor(ans, d[id[i]]);
}
std::cout << ans << endl;
}
}
小trick 可以使用\(bitset\)直接进行异或操作
神奇的代码
std::vector<int> tree[maxn];
std::bitset<100> d[maxn];
std::bitset<100> ans;
int n = 0, m = 0, L = 0;
void dfs(int root)
{
for (int i = 0; i < tree[root].size(); i++)
{
int t = tree[root][i];
d[t] ^= d[root];
dfs(t);
}
}
void solve()
{
std::cin >> n >> m >> L;
int u = 0, v = 0;
for (int i = 1; i <= n - 1; i++)
{
std::cin >> u >> v >> d[v];
tree[u].push_back(v);
}
int tmp = 0;
std::vector<int> id(m + 1, 0);
for (int i = 1; i <= m; i++)
{
std::cin >> id[i];
}
dfs(1);
if (m & 1)
{
ans = d[id[1]] ^ d[id[m]];
}
else
{
for (int i = 2; i <= m - 1; i++)
{
ans ^= d[id[i]];
}
}
std::cout << ans.to_string().substr(100 - L, L) << endl;
}

浙公网安备 33010602011771号