一、L题
签到题,重要是要读懂题,合成的话单个物品也可以合成其他的。然后有个小坑就是题目中n可以等于m,但也是至少要加一次EMC。(导致作者wa一次)
#include <iostream>
using namespace std;
int main() {
int n,m;
cin>>n>>m;
cout<<max(1,n-m)<<'\n';
return 0;
}
二、k题
排序,注意题目中的顺序是可变的。那么就简单多了。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
void solve() {
vector<int>a(N,0);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
sort(a.begin(), a.begin()+n);
int presum=0,ans=0;
for (int i = 0; i < n; i++) {
if (presum <= a[i]) {
ans++;
presum+=a[i];
}
}
cout << ans << '\n';
}
int main() {
ios_base::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
强化变种一下:如果不可变顺序的话该怎么写呢 -------单调栈
void solve() {
vector<int>a(N,0);
stack<int> s;
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int presum=0;
for (int i = 1; i <= n; i++) {
while (!s.empty()&&a[s.top()]>a[i]) {
if (presum - a[s.top()]<=a[i]) {
presum -= a[s.top()];
s.pop();
}else {
break;
}
}
if (presum<=a[i]) {
s.push(i);
presum+=a[i];
}
}
cout<<s.size()<<'\n';
}
三、A题
x表示星元自动机,y为辅助
a,b,n为题目中的意思
数学公式表达化简,即可。
注意事项:特殊值需要判断,如b= =1,n==0。
#include<bits/stdc++.h>
#define int long long
using namespace std;
void solve() {
int n,a,b;
cin>>n>>a>>b;
if (b==0) {
if (a > 1) {
cout<<a * n<<'\n';
}
else {
cout<<n<<'\n';
}
return;
}
if (n == 1) {
cout<<max(a,1ll)<<'\n';
return;
}
double t = (double)(a + b * n - 1)/(2 * b);
int tp = static_cast<int>(t + 0.5);
tp = min(tp,n);//万一对称轴在区间外,就是n。
int ans = (a + b * (n - tp)) * tp + (n - tp);
cout<<ans<<'\n';
}
signed main() {
ios_base::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int T;
cin>>T;
while(T--) {
solve();
}
return 0;
}
四、H题
主要考察观察能力和逆元求解,需要用到快速幂。
直接说结论:
1. 当 n 为偶数时
(
2
n
−
1
)
(2^{n}-1)
(2n−1) / 3 * 2
节点数的2/3 就是答案;
2. 当 n 为偶数时
(
2
n
−
1
−
1
)
(2^{n}-1 -1)
(2n−1−1) / 3 * 2
节点数的-1(减去根节点) × 2/3
注意计算除法时要用逆元来算,不能直接除
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
const ll mod = 998244353;
ll qmi(ll a,ll b) {
ll ans = 1;
while (b) {
if (b&1) {
ans = ans*a % mod;
}
a = a * a % mod;
b>>=1;
}
return ans;
}//快速幂
void solve() {
int n;
cin >> n;
ll res = qmi(2,n)-1;
ll niyuan3 = qmi(3,mod-2);//求三的逆元,费马小定理
ll ans =0;
if (n%2==0) {
ans = res * niyuan3 * 2 % mod;
}else {
ans = ((res - 1) * niyuan3 * 2 % mod + 1) % mod;
}
cout << ans << '\n';
}
signed main() {
ios_base::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL);
int T;
cin >> T;
while(T--) {
solve();
}
return 0;
}
五、j题
#include<bits/stdc++.h>
using namespace std;
bool f(int x){
for(int i=2;i<=sqrt(x);i++){
if(x%i==0){
return false;
}
}
return true;
}
int main()
{
int n;
cin>>n;
vector<int>ans(n);
int cnt=1;
for(int i=n+1;i<100000;i++){
if(f(i)){
cout<<cnt*i<<" ";
cnt++;
}
if(cnt>n){
break;
}
}
}
六、C题
前缀和 + 多源bfs
1.输入处理:读取网格尺寸和矿场信息。
2.差分数组初始化:标记矿场覆盖区域。
3.多源BFS:计算每个非矿场格子到最近矿场的曼哈顿距离。
4.结果计算:遍历所有非矿场格子,计算最大支撑距离。
5.输出结果:根据计算结果输出最大支撑距离或-1。
#include<bits/stdc++.h>
using namespace std;
const int dx[4] = {0, 0, 1, -1};
const int dy[4] = {1, -1, 0, 0};
int main() {
int n, m, k;
cin >> n >> m >> k;
vector<vector<int>> diff(n + 2, vector<int>(m + 2, 0));//前缀和数组
vector<vector<bool>> vis(n + 1, vector<bool>(m + 1, false));
for (int idx = 0; idx < k; idx++) {
int xx, yy, dis;
cin >> xx >> yy >> dis;
int x_low = max(1, xx - dis);
int x_high = min(n, xx + dis);
int y_low = max(1, yy - dis);
int y_high = min(m, yy + dis);
diff[x_low][y_low] += 1;
if (y_high + 1 <= m) diff[x_low][y_high + 1] -= 1;
if (x_high + 1 <= n) diff[x_high + 1][y_low] -= 1;
if (x_high + 1 <= n && y_high + 1 <= m) diff[x_high + 1][y_high + 1] += 1;
}
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;j++) {
diff[i][j]+=diff[i-1][j]+diff[i][j-1]-diff[i-1][j-1];
}
}//前缀和
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (diff[i][j] > 0) {
vis[i][j] = true;//》0的标记为矿场
}
}
}
//多源bfs
vector<vector<int>> dist(n + 1, vector<int>(m + 1, -1));
queue<pair<int, int>> q;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (vis[i][j]) {
dist[i][j] = 0;
q.push({i, j});
}
}
}
while (!q.empty()) {//计算的是每一个空地到矿场的最短曼哈顿距离
auto [x, y] = q.front();
q.pop();
for (int dir = 0; dir < 4; dir++) {
int nx = x + dx[dir];
int ny = y + dy[dir];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && dist[nx][ny] == -1) {
dist[nx][ny] = dist[x][y] + 1;
q.push({nx, ny});
}
}
}
int ans = -1;
for (int x = 1; x <= n; x++) {
for (int y = 1; y <= m; y++) {
int d_safe = dist[x][y] - 1;
if (d_safe > ans) ans = d_safe;
}
}
if (ans == -1) {
cout << -1 << endl;
} else {
cout << ans << endl;
}
return 0;
}