日常训练2025-1-12
1.日常刷题2025-3-62.日常训练2025-1-23.日常训练2025-1-34.日常训练2025-1-55.日常训练2025-1-86.日常训练2025-1-11
7.日常训练2025-1-12
8.日常训练2025-1-139.日常训练2025-1-1410.日常训练2025-1-1511.日常训练2025-1-1612.日常训练2025-1-1713.日常训练2025-1-1814.日常训练2025-1-1915.日常训练2025-1-2116.日常训练2025-1-2217.日常刷题2025-1-2318.日常训练2025-1-2419.日常刷题2025-1-2520.日常刷题21.日常刷题2025-2-622.日常刷题2025-2-923.日常刷题2025-2-1424.日常刷题2025-2-1525.日常刷题2025-2-1726.日常刷题2025-2-2027.日常刷题2025-2-2128.日常刷题2025-2-2229.日常刷题2025-2-2430.日常刷题2025-2-2631.日常刷题2025-2-2732.日常刷题2025-2-2833.日常刷题2025-3-134.日常刷题2025-3-235.日常刷题2025-3-336.日常刷题2025-3-5日常训练2025-1-12
P2679 [NOIP2015 提高组] 子串
普及+/提高
思路
评述
做DP时可以把能想到的有用的状态都定义出来,后序在把不需要的,或者可以根据其他状态推出来的状态删除,逐渐优化。
代码
#include <bits/stdc++.h> typedef std::pair<long long, long long> pll; typedef std::pair<int, int> pii; #define INF 0x3f3f3f3f #define MOD 1000000007 using i64 = long long; const int N = 1e5+5; void solve(){ int n, m, k; std::cin >> n >> m >> k; std::string a, b; std::cin >> a >> b; a = ' ' + a; b = ' ' + b; std::vector dp(m+1, std::vector<std::vector<int>>(k+1, std::vector<int>(2))); std::vector ndp(m+1, std::vector<std::vector<int>>(k+1, std::vector<int>(2))); dp[0][0][0] = 1; ndp[0][0][0] = 1; for (int i = 1; i <= n; i++){ ndp = dp; for (int j = 1; j <= m; j++){ for (int p = 1; p <= k; p++){ if (a[i] == b[j]){ dp[j][p][1] = (ndp[j-1][p][1] + ndp[j-1][p-1][1]) % MOD + ndp[j-1][p-1][0] % MOD; dp[j][p][1] %= MOD; dp[j][p][0] = (ndp[j][p][1] + ndp[j][p][0]) % MOD; }else{ dp[j][p][1] = 0; dp[j][p][0] = (ndp[j][p][1] + ndp[j][p][0]) % MOD; } } } } std::cout << (dp[m][k][0] + dp[m][k][1]) % MOD << '\n'; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2); int t = 1, i; for (i = 0; i < t; i++){ solve(); } return 0; }
E - Takahashi is Slime 2
rating:绿色
思路
题目的几个关键点
- 每次肯定是找相邻的权值最小的点扩展,如果最小的点都已经无法扩展了,那么就没有点可以扩展了。这个过程有点想Dijstra算法,所以想到要使用优先级队列
- 判断大小只需要用已经有的 ans / x 向上取整就行,必须严格比这个值小。
代码
#include <bits/stdc++.h> typedef std::pair<long long, long long> pll; typedef std::pair<int, int> pii; #define INF 0x3f3f3f3f #define MOD 998244353 using i64 = long long; const int N = 1e5+5; void solve(){ int n, m, x; std::cin >> n >> m >> x; int sx, sy; std::cin >> sx >> sy; std::vector d(n+1, std::vector<i64>(m+1)); int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; std::vector vis(n+1, std::vector<int>(m+1, 0)); for (int i = 1; i <= n; i++){ for (int j = 1; j <= m; j++){ std::cin >> d[i][j]; } } i64 ans = d[sx][sy]; vis[sx][sy] = 1; std::priority_queue<std::pair<i64, std::array<int, 2>>, std::vector<std::pair<i64, std::array<int, 2>>>, std::greater<>> q; for (int i = 0; i < 4; i++){ int dx = sx + dir[i][0]; int dy = sy + dir[i][1]; if (dx <= 0 || dx > n || dy <= 0 || dy > m || vis[dx][dy] == 1) continue; q.push({d[dx][dy], {dx, dy}}); vis[dx][dy] = 1; } while (!q.empty()){ auto [w, arr] = q.top(); q.pop(); // std::cout << w << ' ' << arr[0] << ' ' << arr[1] << '\n'; if (w < ((ans+x-1)/x)){ ans += w; for (int i = 0; i < 4; i++){ int dx = arr[0] + dir[i][0]; int dy = arr[1] + dir[i][1]; if (dx <= 0 || dx > n || dy <= 0 || dy > m || vis[dx][dy] == 1) continue; q.push({d[dx][dy], {dx, dy}}); vis[dx][dy] = 1; } }else{ break; } } std::cout << ans << '\n'; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2); int t = 1, i; for (i = 0; i < t; i++){ solve(); } return 0; }
P1855 榨取kkksc03
rating:普及
思路(经典的01背包问题)
/* 记住核心:每个物品只能选一个时从大体积枚举到小体积,每个物品可以选无数次时从小体积枚举到大体积。 f[i][j][k]:表示前i个愿望中,有j块钱和k的时间的情况下能实现的愿望数量的最大值。 初始化:全0 每个愿望有不实现和实现两种情况 状态转移:f[i][j][k] = max(f[i-1][j][k], f[i-1][j-m[i]][k-t[i]] + 1); 由于第一维只有i和i-1所以可以优化掉 */
代码
#include <bits/stdc++.h> typedef std::pair<long long, long long> pll; typedef std::pair<int, int> pii; #define INF 0x3f3f3f3f #define MOD 998244353 using i64 = long long; const int N = 1e5+5; /* f[i][j][k]:表示前i个愿望中,有j块钱和k的时间的情况下能实现的愿望数量的最大值。 初始化:全0 每个愿望有不实现和实现两种情况 状态转移:f[i][j][k] = max(f[i-1][j][k], f[i-1][j-m[i]][k-t[i]] + 1); 由于第一维只有i和i-1所以可以优化掉 */ void solve(){ int n, M, T; std::cin >> n >> M >> T; std::vector<int> m(n+1), t(n+1); for (int i = 1; i <= n; i++){ std::cin >> m[i] >> t[i]; } std::vector f(M+1, std::vector<int>(T+1)); for (int i = 1; i <= n; i++){ for (int j = M; j >= m[i]; j--){ for (int k = T; k >= t[i]; k--){ f[j][k] = std::max(f[j][k], f[j-m[i]][k-t[i]] + 1); } } } std::cout << f[M][T] << '\n'; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2); int t = 1, i; for (i = 0; i < t; i++){ solve(); } return 0; }
P1775 石子合并(弱化版)
思路(区间DP)
/* 状态定义:f[i][j]表示i...j这个区间合并能得到的最小代价 初始化:f[i][i] = 0,当区间内只有自己时代价为0 状态转移:f[i][j] = min(f[i][j], f[i][k] + f[k+1][j] + sum[j] - sum[i-1]);通过枚举k这个分界线来计算。 */
代码
#include <bits/stdc++.h> typedef std::pair<long long, long long> pll; typedef std::pair<int, int> pii; #define INF 0x3f3f3f3f #define MOD 998244353 using i64 = long long; const int N = 1e5+5; void solve(){ int n; std::cin >> n; std::vector<int> v(n+1), pre(n+1); std::vector f(n+1, std::vector<int>(n+1, INF)); for (int i = 1; i <= n ; i++){ std::cin >> v[i]; pre[i] = pre[i-1] + v[i]; f[i][i] = 0; } for (int l = 2; l <= n; l++){ for (int i = 1; i <= n - l + 1; i++){ int j = i + l - 1; for (int k = 1; k < j; k++){ f[i][j] = std::min(f[i][j], f[i][k] + f[k+1][j] + pre[j] - pre[i-1]); } } } std::cout << f[1][n] << '\n'; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2); int t = 1, i; for (i = 0; i < t; i++){ solve(); } return 0; }
C. Trip to the Olympiad
rating:1500
思路(按位考虑+Trick)
分析题目的暗示的性质,按位考虑
代码1
#include <bits/stdc++.h> typedef std::pair<long long, long long> pll; typedef std::pair<int, int> pii; #define INF 0x3f3f3f3f #define MOD 998244353 using i64 = long long; const int N = 1e5+5; void solve(){ int l, r; std::cin >> l >> r; int ans = 0; int k = 30; while ((r >> k & 1) == (l >> k & 1)){ ans += (r >> k & 1) << k; k--; } ans += 1 << k; if (ans - 1 == l){ std::cout << l << ' ' << ans << ' ' << ans + 1 << '\n'; }else{ std::cout <<l << ' ' << ans << ' ' << ans - 1<< '\n'; } } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2); int t = 1, i; std::cin >> t; for (i = 0; i < t; i++){ solve(); } return 0; }
代码2
#include <bits/stdc++.h> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define eb emplace_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef vector<int> VI; typedef basic_string<int> BI; typedef long long ll; typedef pair<int,int> PII; typedef double db; mt19937 mrand(random_device{}()); const ll mod=1000000007; int rnd(int x) { return mrand() % x;} ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;} // head int l,r; void solve() { scanf("%d%d",&l,&r); for (int b=30;b>=0;b--) if ((l>>b)!=(r>>b)) { int g=(r>>b)<<b; if (r==g) printf("%d %d %d\n",g,g-1,g-2); else printf("%d %d %d\n",g+1,g,g-1); break; } } int _; int main() { for (scanf("%d",&_);_;_--) { solve(); } }
本文作者:califeee
本文链接:https://www.cnblogs.com/califeee/p/18666791
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步