2022牛客多校补题2
D
思路
主要是转化为log不太容易能想到
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define int ll
#define Max 0x3f3f3f3f
#define Min 0x0c0c0c0c0;
using vi = vector<int>;
using pii = pair<int, int>;
using vpii = vector<pii>;
using vvi = vector<vector<int>>;
const int N = 1e3 + 10;
int h[N], e[N << 1], ne[N << 1], idx, ti[N];
double v[N << 1], dis[N];
bool st[N];
int n, m;
void add(int a, int b, double c) {
e[idx] = b, ne[idx] = h[a], v[idx] = c, h[a] = idx++;
}
bool check(long double w) {
double power = log(w);
queue<int> q;
for (int i = 1; i <= n; i++)
dis[i] = 0, q.push(i), st[i] = 1, ti[i] = 1;
while (!q.empty()) {
int u = q.front();
st[u] = 0;
q.pop();
if (ti[u] > n)
return 0;
for (int j = h[u]; ~j; j = ne[j]) {
int to = e[j];
if (dis[to] < dis[u] + v[j] + power) {
dis[to] = dis[u] + v[j] + power;
if (!st[to]) {
q.push(to);
st[to] = 1;
ti[to] = ti[u] + 1;
}
}
}
}
return 1;
}
void sol() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
int a, b, c, d;
cin >> a >> b >> c >> d;
add(b, d, log((double)c / a));
}
long double r = 1, l = 0;
while (r - l > 1e-9) {
long double mid = (r + l) / 2;
if (check(mid)) {
l = mid;
} else
r = mid;
}
cout << fixed << setpre
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
int t;
memset(h, -1, sizeof h);
t = 1;
while (t--)
sol();
}
G
思路
打表找规律,可以发现将数组合之后最长上升子序列和最长下降子序列长度是$$\sqrt{n}$$
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
int x = ceil(sqrt(n)), p = n, o = 0;
while (p >= 0)
{
for (int i = p - x + 1; i <= p; i++)
if (i > 0)
cout << i << ' ';
p -= x;
}
cout << endl;
}
return 0;
}
K
思路
这道题主要是状态表示很难想
dp[i][j][k] 表示b的前i位中,与a的lcs为j,左括号比右括号多k个的方案数
显然j的最大值就是子序列a的长度
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int dp[205][205][205];
char s[205];
const int N = 1e9 + 7;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--)
{
int n, m;
cin >> n >> m;
cin >> s + 1;
for (int i = 0; i <= m; i++)
for (int j = 0; j <= n; j++)
for (int k = 0; k <= m; k++)
dp[i][j][k] = 0;
dp[0][0][0] = 1;
for (int i = 1; i <= m; i++)
{
for (int j = 0; j <= n; j++)
{
for (int k = 0; k <= m; k++)
{
//如果b的第i位要放左括号
dp[i][j + (s[j + 1] == '(')][k + 1] += dp[i - 1][j][k];
dp[i][j + (s[j + 1] == '(')][k + 1] %= N;
if (k)//如果前面已经有多的左括号才可以放右括号
{
如果b的第i位要放右括号
dp[i][j + (s[j + 1] == ')')][k - 1] += dp[i - 1][j][k];
dp[i][j + (s[j + 1] == ')')][k - 1] %= N;
}
}
}
}
cout << dp[m][n][0] << endl;
}
return 0;
}