YACS2023年8月丙组

V_Melville精進録 / 2023-08-28 / 原文

T1:幸运儿

幸运儿是 \((x-1+m-1)\%n+1\)

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;

int main() {
    int n, x, m;
    cin >> n >> x >> m;
    --x;
    
    int ans = (x+m-1)%n+1;
    cout << ans << '\n';
    
    return 0;
}

T2:下降幂多项式

模拟

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using ll = long long;

//const int mod = 998244353;
const int mod = 1000000007;
struct mint {
    ll x;
    mint(ll x=0):x((x%mod+mod)%mod) {}
    mint operator-() const {
        return mint(-x);
    }
    mint& operator+=(const mint a) {
        if ((x += a.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator-=(const mint a) {
        if ((x += mod-a.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator*=(const mint a) {
        (x *= a.x) %= mod;
        return *this;
    }
    mint operator+(const mint a) const {
        return mint(*this) += a;
    }
    mint operator-(const mint a) const {
        return mint(*this) -= a;
    }
    mint operator*(const mint a) const {
        return mint(*this) *= a;
    }
    mint pow(ll t) const {
        if (!t) return 1;
        mint a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }

    // for prime mod
    mint inv() const {
        return pow(mod-2);
    }
    mint& operator/=(const mint a) {
        return *this *= a.inv();
    }
    mint operator/(const mint a) const {
        return mint(*this) /= a;
    }
};
istream& operator>>(istream& is, mint& a) {
    return is >> a.x;
}
ostream& operator<<(ostream& os, const mint& a) {
    return os << a.x;
}

int main() {
    cin.tie(nullptr) -> sync_with_stdio(false);
    
    int n, m;
    cin >> n >> m;
    
    vector<int> a(n+1);
    rep(i, n+1) cin >> a[i];
    
    vector<mint> x(n+1, 1);
    rep(i, n) {
        x[i+1] = x[i]*m;
        m--;
    }
    reverse(x.begin(), x.end());
    
    mint ans;
    rep(i, n+1) {
        ans += x[i]*a[i];
    }
    
    cout << ans << '\n';
    
    return 0;
}

T3:假期

简单dp

dp[i][j] 表示第 \(i\) 天选择了活动 \(j\) 使得前 \(i\) 天得到分数总和的最大值

原题:Vacation

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;

inline void chmax(int& x, int y) { if (x < y) x = y; }

int main() {
    int n;
    cin >> n;
    
    vector dp(n+1, vector<int>(3));
    rep(i, n) {
        vector<int> a(3);
        rep(j, 3) cin >> a[j];
        rep(j, 3)rep(k, 3) if (j != k) {
            chmax(dp[i+1][j], dp[i][k]+a[j]);
        }
    }
    
    int ans = 0;
    rep(i, 3) chmax(ans, dp[n][i]);
    
    cout << ans << '\n';
    
    return 0;
}

T4:素数行列

  • 先筛出 \(2e5\) 以内所有的素数
  • 然后求出每个数变成大于或等于它的第一个素数的代价
  • 最后遍历每行每列里所有数的代价总和取最小值即可

原题:CF271B

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using ll = long long;

// linear sieve
vector<bool> isp;
vector<int> ps, pf;
void sieve(int mx) {
    isp.resize(mx+1);
    pf.resize(mx+1);
    rep(i, mx+1) pf[i] = i;
    for (int i = 2; i <= mx; ++i) {
        if (pf[i] == i) isp[i] = true, ps.push_back(i);
        rep(j, ps.size()) {
            int x = ps[j] * i;
            if (x > mx) break;
            pf[x] = ps[j];
        }
    }
}

int main() {
    sieve(2e5);
    
    int n;
    cin >> n;
    
    vector c(n, vector<int>(n));
    rep(i, n)rep(j, n) {
        int x;
        cin >> x;
        while (!isp[x]) {
            x++;
            c[i][j]++;
        }
    }
    
    int ans = 1001001001;
    rep(i, n) {
        int s = 0;
        rep(j, n) s += c[i][j];
        ans = min(ans, s);
    }
    rep(j, n) {
        int s = 0;
        rep(i, n) s += c[i][j];
        ans = min(ans, s);
    }
    
    cout << ans << '\n';
    
    return 0;
}

T5:方格路径

注意到这题可以向上或向左走,不满足无后效性,所以不能 \(\operatorname{dp}\)

我们可以用 \(\operatorname{bfs}\) \(+\) 简单递推解决

在我们求到当前点的最短路时,可以同时更新到当前的最短路的路径数

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using ll = long long;
using P = pair<int, int>;

//const int mod = 998244353;
const int mod = 1000000007;
struct mint {
    ll x;
    mint(ll x=0):x((x%mod+mod)%mod) {}
    mint operator-() const {
        return mint(-x);
    }
    mint& operator+=(const mint a) {
        if ((x += a.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator-=(const mint a) {
        if ((x += mod-a.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator*=(const mint a) {
        (x *= a.x) %= mod;
        return *this;
    }
    mint operator+(const mint a) const {
        return mint(*this) += a;
    }
    mint operator-(const mint a) const {
        return mint(*this) -= a;
    }
    mint operator*(const mint a) const {
        return mint(*this) *= a;
    }
    mint pow(ll t) const {
        if (!t) return 1;
        mint a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }

    // for prime mod
    mint inv() const {
        return pow(mod-2);
    }
    mint& operator/=(const mint a) {
        return *this *= a.inv();
    }
    mint operator/(const mint a) const {
        return mint(*this) /= a;
    }
};
istream& operator>>(istream& is, mint& a) {
    return is >> a.x;
}
ostream& operator<<(ostream& os, const mint& a) {
    return os << a.x;
}

const int di[] = {0, 1, 0, -1};
const int dj[] = {1, 0, -1, 0};

int main() {
	int n, m;
	cin >> n >> m;
	
	vector<string> s(n);
	rep(i, n) cin >> s[i];
	
	const int INF = 1001001001;
	vector dist(n, vector<int>(m, INF));
	vector dp(n, vector<mint>(m));
	queue<P> q;
	dist[0][0] = 1; 
	dp[0][0] = 1;
	q.emplace(0, 0);
	while (q.size()) {
	    auto [i, j] = q.front(); q.pop();
	    rep(v, 4) {
	        int ni = i+di[v], nj = j+dj[v];
	        if (ni < 0 or ni >= n or nj < 0 or nj >= m or s[ni][nj] == '#') continue;
	        if (dist[ni][nj] == INF) {
	            dist[ni][nj] = dist[i][j]+1;
	            q.emplace(ni, nj);
	        }
	        if (dist[ni][nj] == dist[i][j]+1) {
	            dp[ni][nj] += dp[i][j];
	        }
	    }
	}
	
	cout << dp[n-1][m-1] << '\n';
	
	return 0;
}