A 九进制转十进制
思路
简单进制转化
代码
#include <bits/stdc++.h>
using namespace std;
int n = 2022;
int sum = 0;
int t = 0;
int main() {
while (n > 0) {
sum += pow(9, t) * (n % 10);
n /= 10;
t++;
}
cout << sum;
return 0;
}
B 顺子日期
思路
日期计算,遍历每一个日期并判断
代码
#include <bits/stdc++.h>
using namespace std;
string month[13] = {"0", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"};
int mday[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int ans = 0;
void cheak(string s) {
int cnt = 1;
int res = 0;
for (int i = 0; i < s.size() - 1; i++) {
if (s[i] + 1 == s[i + 1]) {
cnt++;
res = max(res, cnt);
} else cnt = 1;
}
if (res >= 3) ans++;
}
int main() {
for (int i = 1; i <= 12; i++) {
for (int j = 1; j <= mday[i]; j++) {
string s = "2022";
s += month[i];
if (j < 10) s += '0';
s += to_string(j);
cheak(s);
}
}
cout << ans;
return 0;
}
C 刷题统计
思路
先算周数,再算天数,注意开longl ong
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll a, b, n;
ll ans = 0;
int main() {
cin >> a >> b >> n;
ll week = 0;
ll k = 5 * a + 2 * b;
week = n / k;
n %= k;
if (5 * a < n) {
n -= 5 * a;
ans += 5;
ans += n / b;
if (n % b != 0) ans++;
} else {
ans += n / a;
if (n % a != 0) ans++;
}
ans += week * 7;
cout << ans;
return 0;
}
D 修剪灌木
思路
找规律,最大值为离两端的距离*2的较大者
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5;
int n;
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cout << 2 * max(n - i, i - 1) << endl;
return 0;
}
E X进制减法
思路
简单数学计算,当进制X_i最小时,A-B最小
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 1e9 + 7;
ll n, m;
ll ma, mb;
stack<ll> a, b;
ll x, y;
ll ans, res = 1;
int main() {
cin >> n;
cin >> ma;
for (int i = 1; i <= ma; i++) cin >> m, a.push(m);
cin >> mb;
for (int i = 1; i <= mb; i++) cin >> m, b.push(m);
int x, y;
while (!a.empty()) {
x = a.top(), a.pop();
if (!b.empty()) y = b.top(), b.pop();
else y = 0;
ans += (x - y + mod) % mod * res % mod;
ans %= mod;
res *= max(2, max(x, y) + 1);
res %= mod;
}
cout << ans;
return 0;
}
F 统计子矩阵
思路
暴力前缀和过不了,得用双指针优化下
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 5e2 + 5;
ll a[N][N], s[N][N];
int n, m;
ll ans, k;
int main() {
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
s[j][i] = s[j][i - 1] + a[i][j];
}
}
for (int u = 1; u <= n; u++) {
for (int d = u; d <= n; d++) {
int l = 1, r = 1;
ll sum = s[1][d] - s[1][u - 1];
while (r <= m) {
if (sum <= k) {
ans += r - l + 1;
r++;
sum += s[r][d] - s[r][u - 1];
} else {
sum -= s[l][d] - s[l][u - 1];
l++;
}
}
}
}
cout << ans;
return 0;
}
G 积木画
思路
找规律递推
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e7 + 5;
const ll mod = 1000000007;
ll dp[N];
int n;
int main() {
cin >> n;
dp[1] = 1;
dp[2] = 2;
dp[3] = 5;
for (int i = 4; i <= n; i++) {
dp[i] = 2 * dp[i - 1] + dp[i - 3];
dp[i] %= mod;
}
cout << dp[n];
return 0;
}
H 扫雷
思路
直接搜索会暴,考虑优化,由于雷一定会在(x-r,x+r)的范围内,所以采用二分查找出两个边界,循环该范围内的雷即可
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 5e4 + 5;
struct node {
int x, y;
int r;
bool is;
} a[N], b[N];
int ans = 0;
double len(int x1, int y1, int x2, int y2) {
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
bool cmp(node a, node b) {
return a.x < b.x;
}
int n, m;
void boom(node b) {
int lmid, rmid;
int L = 1, R = n;
while (L <= R) {
lmid = (L + R) / 2;
if (a[lmid].x < b.x - b.r) L = lmid + 1;
else R = lmid - 1;
}
lmid = L;
L = 1, R = n;
while (L <= R) {
rmid = (L + R) / 2;
if (a[rmid].x <= b.x + b.r) L = rmid + 1;
else R = rmid - 1;
}
for (int i = lmid; i <= rmid; i++) {
if (!a[i].is && b.r >= len(b.x, b.y, a[i].x, a[i].y)) {
ans++;
a[i].is = 1;
boom(a[i]);
}
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i].x >> a[i].y >> a[i].r;
for (int i = 1; i <= m; i++) cin >> b[i].x >> b[i].y >> b[i].r;
sort(a + 1, a + 1 + n, cmp);
for (int i = 1; i <= m; i++) boom(b[i]);
cout << ans;
return 0;
}
I 李白打酒加强版
思路
简单动态规划
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 1e9 + 7;
int n, m;
ll dp[205][105][105];
int main() {
cin >> n >> m;
dp[0][0][2] = 1;
for (int i = 0; i < n + m; i++) {
for (int j = 0; j < m; j++) {
for (int k = 0; k <= m; k++) {
if (dp[i][j][k]) {
if (k > 0) dp[i + 1][j + 1][k - 1] = (dp[i + 1][j + 1][k - 1] + dp[i][j][k]) % mod;
if (k <= 50) dp[i + 1][j][k * 2] = (dp[i + 1][j][k * 2] + dp[i][j][k]) % mod;
}
}
}
}
cout << dp[n + m][m][0];
return 0;
}
J 砍竹子
思路
每次砍最大的,用堆实现,把连续的一段当作一个整体,注意用sqrtl
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5 + 5;
ll magic(ll h) {
ll s = h / 2 + 1;
s = floor(sqrtl(s));
return s;
}
int n;
ll a[N];
ll ans = 0;
ll l[N];
struct node {
ll h;
ll i;
friend bool operator<(node a, node b) {
if (a.h == b.h) return a.i < b.i;
return a.h < b.h;
}
};
priority_queue<node> q;
int main() {
cin >> n;
for (int i = 1; i <= n + 1; i++) l[i] = i - 1;
for (int i = 1; i <= n; i++) {
cin >> a[i];
q.push({a[i], i});
}
while (1) {
node ma = q.top();
q.pop();
if (ma.h == 1) break;
ll x = ma.i;
while (a[l[x]] == ma.h) {
q.pop();
x = l[x];
l[ma.i] = l[x];
}
a[ma.i] = magic(ma.h);
q.push({magic(ma.h), ma.i});
ans++;
}
cout << ans;
return 0;
}