Link
每天补题就好忙了,没时间写思路QWQ,有时间就写思路
A. Aahaxiki’s journey I - set off
思路
d
i
j
k
s
t
r
a
dijkstra
dijkstra 算法,没啥说的
思路就是拆点,把机场和火车站拆开,建图
考虑:
- 起点机场 -> 终点机场
- 起点机场 -> 终点火车
- 起点火车 -> 终点机场
- 起点火车 -> 终点火车
- 特判 n = 1 n = 1 n=1 的时候
两次
d
i
j
k
s
t
r
a
dijkstra
dijkstra 就够用
注意,这题会卡常数,必须快读
#include <bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define MP make_pair
#define PB push_back
typedef pair<int, int> PII;
typedef vector<int> VI;
const int N = 3e5 + 10;
int n, m, l, x, y;
struct Edg{
int v, x, y;
bool operator< (const Edg &w) const {
if (x != w.x) return x > w.x;
else return y > w.y;
}
};
vector<Edg> g[N];
int read()
{
int X=0; bool flag=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
if(flag) return X;
return ~(X-1);
}
PII dijkstra(int st) {
vector<PII> dis(n << 1 | 1);
vector<bool> vis(n << 1 | 1);
fill(dis.begin() + 1, dis.end(), MP(INF, INF));
dis[st] = {0, 0};
priority_queue<Edg> q;
q.push({st, 0, 0});
while (q.size()) {
auto tmp = q.top(); q.pop();
int j = tmp.v;
if (vis[j]) continue;
vis[j] = 1;
for (auto t : g[j]) {
int v = t.v;
if (dis[v] > MP(dis[j].FI + t.x, dis[j].SE + t.y)) {
dis[v] = MP(dis[j].FI + t.x, dis[j].SE + t.y);
q.push({v, dis[v].FI, dis[v].SE});
}
}
}
return min(dis[n], dis[n * 2]);
}
int main() {
int t;
t = read();
while (t -- ) {
n = read(), m = read(), l = read(), x = read(), y = read();
for (int i = 1; i <= n * 2; i ++ ) g[i].clear();
if (n == 1) {
printf("%d %d\n", x, y);
continue;
}
for (int i = 1; i <= m; i ++ ) {
int u, v, a, b;
u = read(), v = read(), a = read(), b = read();
g[u].PB({v, a, b}), g[v].PB({u, a, b});
}
for (int i = 1; i <= l; i ++ ) {
int u, v, a, b;
u = read(), v = read(), a = read(), b = read();
g[u + n].PB({v + n, a, b}), g[v + n].PB({u + n, a, b});
}
for (int i = 1; i <= n; i ++ ) {
g[i].PB({n + i, x, y}), g[n + i].PB({i, x, y});
}
PII ans1 = dijkstra(1);
PII ans2 = dijkstra(n + 1);
PII ans = min(ans1, ans2);
if (ans.FI == INF) puts("-1");
else printf("%d %d\n", ans.FI + 2 * x, ans.SE + 2 * y);
}
return 0;
}
B. Bsueh- and Gold Medals
思路
简单二分和贪心
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int a[N];
int n, m;
bool check(int mid) {
int cnt = 1, pre = a[1];
for (int i = 2; i <= n; i ++ ) {
if (a[i] - pre >= mid) {
cnt ++;
pre = a[i];
}
}
if (cnt >= m) return 1;
else return 0;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t -- ) {
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
sort(a + 1, a + n + 1);
int l = 0, r = 1e6;
while (l < r) {
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
cout << l << endl;
}
return 0;
}
C. Chtholly and Floating Islands
思路
q
q
q 太大,必须预处理
数据范围提示状压
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int a[15], b[15];
int dp[N];
int ans[N];
int n, m, k;
void init() {
for (int cnt = 0; cnt < (1 << k); cnt ++ ) {
for (int i = 1; i <= n; i ++ ) dp[i] = 0;
dp[1] = 1;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
if (i - a[j] <= 0) continue;
dp[i] = (dp[i - a[j]] + dp[i]) % mod;
}
for (int k = 0; (cnt >> k) > 0; k ++ ) {
if ((cnt >> k) & 1) {
if (i - b[k + 1] <= 0) continue;
dp[i] = (dp[i - b[k + 1]] + dp[i]) % mod;
}
}
}
ans[cnt] = dp[n];
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m >> k;
for (int i = 1; i <= m; i ++ ) cin >> a[i];
for (int i = 1; i <= k; i ++ ) cin >> b[i];
init();
int q;
cin >> q;
while (q -- ) {
int c;
cin >> c;
int res = 0;
for (int i = 1; i <= c; i ++ ) {
int t;
cin >> t;
res += 1 << (t - 1);
}
cout << ans[res] << endl;
}
return 0;
}
E. Ewo Slices of Bread with Cheese
思路
签到
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
int odd = 0, even = 0;
for (int i = 1; i <= n; i ++ ) {
int a;
cin >> a;
if (a & 1) odd ++;
else even ++;
}
int ans = 0;
if (odd == even) ans = odd + even;
else if (odd > even) {
ans += even * 2;
odd -= even;
ans += odd * 2;
} else {
ans += 2 * odd;
even -= odd;
ans += even * 2 - 1;
}
cout << ans << endl;
return 0;
}
F. Fstee1XD and Minioins
思路
如果数感好的话,能看出来是斐波那契的奇数项
如果看不出来,我们也可以推出
f
[
n
]
=
3
∗
f
[
n
−
1
]
−
f
[
n
−
2
]
f[n] = 3 * f[n -1] - f[n - 2]
f[n]=3∗f[n−1]−f[n−2]
n
n
n 很大,考虑矩阵快速幂
要构造出矩阵
A
A
A,满足
{
f
[
n
−
1
]
f
[
n
−
2
]
}
∗
A
=
{
f
[
n
]
f
[
n
−
1
]
}
\left\{ \begin{matrix} f[n - 1] \\ f[n - 2] \\ \end{matrix} \right\} *A = \left\{ \begin{matrix} f[n ] \\ f[n - 1] \\ \end{matrix} \right\}
{f[n−1]f[n−2]}∗A = {f[n]f[n−1]}
易得
A
=
[
3
1
−
1
0
]
A = \left[ \begin{matrix} 3 & 1 \\ -1 & 0 \\ \end{matrix} \right]
A = [3−110]
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
void mul(LL f[2], LL a[2][2]) {
LL c[2];
memset(c, 0, sizeof c);
for (int j = 0; j < 2; j ++ )
for (int k = 0; k < 2; k ++ )
c[j] = (c[j] + (LL) f[k] * a[k][j]) % mod;
memcpy(f, c, sizeof c);
}
void mulself(LL a[2][2]) {
LL c[2][2];
memset(c, 0, sizeof c);
for (int i = 0; i < 2; i ++ )
for (int j = 0; j < 2; j ++ )
for (int k = 0; k < 2; k ++ )
c[i][j] = (c[i][j] + (LL) a[i][k] * a[k][j]) % mod;
memcpy(a, c, sizeof c);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t -- ) {
LL n;
cin >> n;
n *= 2, n --;
LL a[2][2] = {{0, 1}, {1, 1}};
LL f[2] = {0, 1};
for (; n; n >>= 1) {
if (n & 1) mul(f, a);
mulself(a);
}
cout << f[0] << endl;
}
return 0;
}
G. Guess Permutation
思路
数据范围提示二进制
每个数字都是不一样的,那么我们对所有数字从
1
1
1 到
n
n
n 进
行编号
将编号作为
2
2
2 进制表示,第 i 次询问所有在第
i
−
1
i − 1
i−1 位为
1
1
1 的编号,统计路径
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
VI res;
int ans[N];
bool tmp[15][N];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
for (int i = 0; i < 11; i ++ ) {
res.clear();
for (int j = 1; j <= n; j ++ ) {
if ((j >> i) & 1) res.PB(j);
}
if (res.empty()) continue;
cout << res.size() << ' ';
for (auto t : res) cout << t << ' ';
cout << endl;
cout.flush();
for (int j = 1; j <= res.size(); j ++ ) {
int s;
cin >> s;
tmp[i][s] = 1;
}
}
for (int i = 1; i <= n; i ++ ) {
int pos = 0;
for (int j = 0; j < 11; j ++ )
if (tmp[j][i]) pos += 1 << j;
ans[pos] = i;
}
cout << "! ";
for (int i = 1; i <= n; i ++ ) cout << ans[i] << ' ';
return 0;
}
H. Hsueh- and Meeting
思路
将人和座位绑定,然后选位置给第一个人,选这个位置有
m
m
m 种方案,剩下的
m
−
n
−
1
m - n - 1
m−n−1 个位置放
n
−
1
n - 1
n−1 个人,
n
−
1
n - 1
n−1 个人全排列
答案
C m − n − 1 n − 1 ∗ m ∗ ( n − 1 ) ! C_{m - n - 1} ^ {n - 1} * m * (n - 1)! Cm−n−1n−1∗m∗(n−1)!
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
LL f[N], inv[N];
LL qi(LL a) {
LL ans = 1;
int b = mod - 2;
while (b) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
void init() {
f[0] = 1, inv[0] = 1;
for (int i = 1; i < N; i ++ ) {
f[i] = f[i - 1] * i % mod;
inv[i] = qi(f[i]);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
init();
int t;
cin >> t;
while (t -- ) {
int n, m;
cin >> n >> m;
if (n == 1) {
cout << m << endl;
continue;
} else if (m < 2 * n) {
cout << 0 << endl;
continue;
} else {
cout << m * f[n - 1] % mod * f[m - n - 1] % mod * inv[n - 1] % mod * inv[m - 2 * n] % mod << endl;
}
}
return 0;
}
J. Jahaxiki’s journey III - Tryna lost
思路
模拟
就是读入图案有点麻烦
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
typedef vector<int> VI;
const int N = 2e5 + 10;
int n, m;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
vector<VI> g;
vector<VI> st;
char ch[N];
bool ok = 1;
void dfs(int a, int b, int ti) {
st[a][b] = ti;
for (int i = 0; i < 4; i ++ ) {
if ((g[a][b] >> i) & 1) continue;
int x = a + dx[i], y = b + dy[i];
if (x < 1 || x > n || y < 1 || y > m) continue;
if (st[x][y] && st[x][y] + 1 != ti) {
ok = 0;
return;
} else if (st[x][y]) continue;
dfs(x, y, ti + 1);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
for (int i = 0; i <= n + 1; i ++ ) {
VI tmp;
VI t;
for (int j = 0; j <= m + 1; j ++ ) {
tmp.PB(0);
t.PB(0);
}
g.PB(tmp);
st.PB(t);
}
cin >> ch;
for (int i = 0; i <= n; i ++ ) {
cin.getline(ch, 2 * m + 2);
for (int j = 0; j <= 2 * m; j ++ ) {
int r = i, c = j / 2;
if (ch[j] == '|') {
g[r][c] += 2;
g[r][c + 1] += 8;
} else if (ch[j] == '_') {
c ++;
g[r][c] += 4;
g[r + 1][c] += 1;
}
}
}
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ ) {
if (!st[i][j]) dfs(i, j, 1);
if (!ok) break;
}
if (ok) puts("YES");
else puts("NO");
return 0;
}