A题
给出n,k,求三个数x/y/z,使得n = x + y + z,并且gcd(x,y) = gcd(x,z) = gcd(y,z) = k
解:在n / k / 3范围内左右查找符合条件的值
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll t,n,k; int solve() { if(n % k) return 0; ll p = n / k; ll r = p / 3; for(ll i = max(2LL,r - 100);i <= min(p,r + 100); ++i) for(ll j = max(2LL,r - 100);j <= min(p,r + 100); ++j) { if(p - i - j <= 1 || __gcd(i,j) != 1 || __gcd(i,p - i - j) != 1 || __gcd(j,p - i - j) != 1) continue; cout<<i * k<<' '<<j * k<<' '<<(p - i - j) * k<<'\n'; return 1; } return 0; } int main() { std::ios::sync_with_stdio(false); cin>>t; while(t--) { cin>>n>>k; if(!solve()) cout<<"-1 -1 -1\n"; } return 0; }
B题
求分子式的质量
解:栈的基础应用
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5 + 10; string a; ll n,ans,k; stack<ll>s; void check() { if(k) { k *= s.top(); s.pop(); s.push(k); k = 0; } } int main() { std::ios::sync_with_stdio(false); cin>>a; n = a.size(); k = 0; for(int i = 0;i < n; ++i) { if(a[i] == '(') check(),s.push(-1); else if(a[i] == ')') { check(); int sum = 0; while(!s.empty() && s.top() != -1) { sum += s.top(); s.pop(); } if(!s.empty() && s.top() == -1) s.pop(); if(sum) s.push(sum); } else if(a[i] >= '0' && a[i] <= '9') k = k * 10 + a[i] - '0'; else if(a[i] == 'C') check(),s.push(13LL); else if(a[i] == 'H') check(),s.push(1LL); else if(a[i] == 'O') check(),s.push(17LL); } check(); while(!s.empty()) ans += s.top(),s.pop(); cout<<ans<<'\n'; return 0; }
C题 简单模拟
F题 最后先手必胜
G题
选择(n/2)(向下取整)个才能拿走,并且不能选择在数组中相邻的数,一定要选第x个数,问选出的数的最大的和
解:很显然是DP,必须要选第x个,可以给第x个加上一个很大的数,最后减掉即可。
由于奇数时向下取整会损失精度,所以要分奇偶讨论
奇数:
第i个数字选或者不选 dp[i] = max{dp[i- 1],dp[i - 2] + a[i]}
偶数:
第i个数字选或者不选 dp[i] = max{sum[i- 1],dp[i - 2] + a[i]} //如果用dp[i - 1]会少选一个,sum[i - 1]是唯一选法
代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll p = 1e16; ///一定要足够大 const int maxn = 2e5 + 10; ll n,x,a[maxn],dp[maxn],sum[maxn]; int main() { std::ios::sync_with_stdio(false); cin>>n>>x; for(int i = 1;i <= n; ++i) cin>>a[i]; a[x] += p; sum[1] = a[1]; for(int i = 3;i <= n; i += 2) sum[i] = sum[i - 2] + a[i]; for(int i = 2;i <= n; ++i) { if(i % 2) dp[i] = max(dp[i - 1],dp[i - 2] + a[i]); else dp[i] = max(sum[i - 1],dp[i - 2] + a[i]); } cout<<(dp[n] - p)<<'\n'; return 0; }
I题
构造一个n×m的矩阵,使矩阵中任意相邻的两个数高度差都恰好为1,给出k条信息,说明(xi,yi)这个点的高度为hi。
解:从高度最小的点开始向四个方向bfs即可
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; const int ma = 1e9 + 1; int n,m,k; vector<int>a[maxn]; ///数组开不下 vector<bool>vis[maxn]; int x,y,h; int d[4][2] = {{-1,0},{0,-1},{0,1},{1,0}}; struct node { int x,y; int h; node(int _x,int _y,int _h):x(_x),y(_y),h(_h){} bool operator<(const node& a) const //注意区分 { return h > a.h; } }; priority_queue<node>q; bool solve() { if(k) { while(k--) { cin>>x>>y>>h; if(a[x][y] != -ma && a[x][y] != h) return 0; a[x][y] = h; vis[x][y] = 1; q.push(node(x,y,h)); } } else //k = 0时 { a[1][1] = 0; q.push(node(1,1,0)),vis[1][1] = 1; } // cout<<q.size()<<endl; while(!q.empty()) { node r = q.top(); q.pop(); for(int i = 0;i < 4; ++i) { int xx = r.x + d[i][0]; int yy = r.y + d[i][1]; if(xx > n || xx < 1 || yy > m || yy < 1 || vis[xx][yy]) continue; if(a[xx][yy] != -ma && a[xx][yy] != r.h + 1) return 0; a[xx][yy] = r.h + 1; q.push(node(xx,yy,r.h + 1)); vis[xx][yy] = 1; } } for(int i = 1;i <= n; ++i) for(int j = 1;j <= m; ++j) for(int kk = 0;kk < 4; ++kk) { int xx = i + d[kk][0]; int yy = j + d[kk][1]; if(xx > n || xx < 1 || yy > m || yy < 1) continue; if(abs(a[i][j] - a[xx][yy]) != 1) return 0; } return 1; } int main() { std::ios::sync_with_stdio(false); cin>>n>>m>>k; for(int i = 1;i <= n + 1; ++i) for(int j = 1;j <= m + 1; ++j) a[i].push_back(-ma),vis[i].push_back(0); if(solve()) { cout<<"Yes\n"; for(int i = 1;i <= n; ++i) for(int j = 1;j <= m; ++j) cout<<a[i][j]<<((j == m)?'\n':' '); } else cout<<"No\n"; return 0; }