The 2021 Hangzhou Normal U Summer Trials

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]=3f[n1]f[n2]
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[n1]f[n2]}  {f[n]f[n1]}
易得
A   =   [ 3 1 − 1 0 ] A =  \left[ \begin{matrix} 3 & 1 \\ -1 & 0 \\ \end{matrix} \right]   [3110]

#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 i1 位为
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 mn1 个位置放 n − 1 n - 1 n1 个人, n − 1 n - 1 n1 个人全排列
答案

C m − n − 1 n − 1 ∗ m ∗ ( n − 1 ) ! C_{m - n - 1} ^ {n - 1} * m * (n - 1)! Cmn1n1m(n1)!

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值