2022“杭电杯”中国大学生算法设计超级联赛(4)
[题目链接](Search Result (hdu.edu.cn))
D Link with Equilateral Triangle
题目大意
有一个边长为n的等边三角形,由n2个边长为1的等边三角形组成。在小三角形的顶点填数0,1,2,同时要求在大三角形的左边不能填0,右边不能填1,下边不能填2,且小三角形的三个数加起来不能是3的倍数。问是否可以填出来。
题解
直接输出No。
代码
#include <iostream>
using namespace std;
int t, n;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> t;
while (t--)
{
cin >> n;
cout << "No" << endl;
}
return 0;
}
F BIT Subway
题目大意
现有一个优惠政策,累计购票满100后,再次购票打八折;满200后,再次购票打五折。有一个人误解了优惠政策,认为是未满,买一张票以后满的部分已经可以打折。问误解总收费和实际总收费。
题解
分段函数。
代码
#include <iostream>
#include <iomanip>
using namespace std;
int t, n;
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
double ans1 = 0, ans2 = 0;
for (int i = 1; i <= n; i++)
{
double x;
scanf("%lf", &x);
if (ans2 < 100)
ans2 += x;
else if (ans2 < 200)
ans2 += 0.8 * x;
else
ans2 += 0.5 * x;
ans1 += x;
}
if (ans1 < 100)
ans1 = ans1;
else if (ans1 < 225)
ans1 = (ans1 - 100) * 0.8 + 100;
else
ans1 = (ans1 - 225) * 0.5 + 200;
printf("%.3lf %.3lf\n", ans1, ans2);
}
return 0;
}
G Climb Stairs
题目大意
一共有n个怪物,每个怪物都有ai的血量,初始DLee有a0的攻击力。当DLee的攻击力大于等于怪物的血量,就可以干掉怪物,并且攻击力会加上怪物的血量。DLee初始在0这个位置上,当在点i上,每次DLee可以选择向上跳到 i+x点(1≤x≤k)或者向下跳到i-1点,且不能经过已经经过的点。问能否打完全部的怪物。
题解
打怪物的方案:对于一个起点now,找到一个可以打怪物的最近的点i(now+1≤i≤now+k),然后我们一路打回now+1。然后把now+1看成新的now,重复上述过程。
判断可以一路打回来的条件:定义一个ma,为打到当前层需要的最少的攻击力,ma = max(a[i], ma - a[i])。
代码
#include <iostream>
#include <iomanip>
using namespace std;
const int maxn = 1e5 + 5;
int t, n, a0, k;
int a[maxn];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--)
{
cin >> n >> a0 >> k;
for (int i = 1; i <= n; i++)
cin >> a[i];
int now = 0, kk = k, ma = 0;
bool flag;
while (1)
{
flag = 0;
for (int i = now + 1; i <= n && i <= now + k; i++)
{
ma = max(a[i], ma - a[i]);
if (ma <= a0)
{
flag = 1;
for (int j = now + 1; j <= i; j++)
a0 += a[j];
k = now + 1 + kk - i;
now = i;
}
}
if (flag == 0)
break;
if (now == n)
break;
}
if (flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}
A Link with Bracket Sequence II
题目大意
一共有m种括号。现给出一个残缺的括号序列,长为n,问有多少种填充方式,使得最后是一个合法的括号序列。ai=0表示这个位置上残缺括号,ai>0表示这个位置上有ai类型的左括号,ai<0表示这个位置上有ai类型的右括号。
题解
定义dp(i,j)为区间(i,j)可以产生多少种合法的括号序列。
一共有两种情况al=0或al>0。
若al=0,①ai=0,res += m * dfs(l + 1, i - 1) * dfs(i + 1, r);②ai<0,res += dfs(l + 1, i - 1) * dfs(i + 1, r)。
若al>0,①ai=0,res += dfs(l + 1, i - 1) * dfs(i + 1, r);②ai=-al,res += dfs(l + 1, i - 1) * dfs(i + 1, r)。
代码
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 5e2 + 5;
ll n, m, t;
ll a[maxn];
ll dp[maxn][maxn];
ll dfs(ll l, ll r)
{
if (dp[l][r] != -1)
return dp[l][r];
if ((r - l + 1) % 2)
return dp[l][r] = 0;
if (l > r)
return dp[l][r] = 1;
ll res = 0;
if (a[l] == 0)
{
for (ll i = l + 1; i <= r; i += 2)
{
if (a[i] == 0)
res = (res + m * dfs(l + 1, i - 1) % mod * dfs(i + 1, r)) % mod;
else if (a[i] < 0)
res = (res + dfs(l + 1, i - 1) * dfs(i + 1, r)) % mod;
}
}
else if (a[l] > 0)
{
for (ll i = l + 1; i <= r; i += 2)
{
if (a[i] == 0)
res = (res + dfs(l + 1, i - 1) * dfs(i + 1, r)) % mod;
else if (a[i] == -a[l])
res = (res + dfs(l + 1, i - 1) * dfs(i + 1, r)) % mod;
}
}
return dp[l][r] = res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--)
{
memset(dp, -1, sizeof dp);
cin >> n >> m;
for (ll i = 1; i <= n; i++)
cin >> a[i];
cout << dfs(1, n) << endl;
}
}
K Link is as bear
题目大意
给定一个数组a,你可以多次执行以下操作,选择一段区间[L,R],将区间赋值为区间的异或和,最后使得整个数组都变得相等,问最大的相等的数是多少。
题解
官方题解。
代码
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
const int maxl = 60;
int t, n;
ll x[maxn];
struct LinearBasis
{
ll a[maxl + 1];
LinearBasis()
{
fill(a, a + maxl + 1, 0);
}
LinearBasis(ll *x, int n)
{
build(x, n);
}
void insert(ll t)
{
for (int j = maxl; j >= 0; j--)
{
if (!t)
return;
if (!(t & (1ll << j)))
continue;
if (a[j])
t ^= a[j];
else
{
for (int k = 0; k < j; k++)
if (t & (1ll << k))
t ^= a[k];
for (int k = j + 1; k <= maxl; k++)
if (a[k] & (1ll << j))
a[k] ^= t;
a[j] = t;
break;
}
}
}
void build(ll *x, int n)
{
fill(a, a + maxl + 1, 0);
for (int i = 1; i <= n; i++)
{
insert(x[i]);
}
}
ll queryMax()
{
ll res = 0;
for (int i = 0; i <= maxl; i++)
res ^= a[i];
return res;
}
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--)
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> x[i];
LinearBasis res(x, n);
cout << res.queryMax() << endl;
}
}