1531-奇怪的数字
思路:模拟即可
#include <iostream>
#include <vector>
#include <string>
int main()
{
int n = 1000000;
for (int i = 100;i <= n;i++) {
std::string s = std::to_string(i);
std::vector<int>mp(10, 0);
for (auto& ss : s) {
mp[ss - '0']++;
}
for (auto& ss : s) {
int num = ss - '0';
if (num == 0) continue;
std::vector<int>mp1 = mp;
if (i % num == 0) {
int nextNum = i / num;
//std::cout << i << " " << num << " " << nextNum << std::endl;
std::string st = std::to_string(nextNum);
mp1[num]--;
for (auto& sst : st) {
mp1[sst - '0']--;
}
}
bool is = false;
for (auto& m : mp1) {
if (m != 0) {
is = true;
break;
}
}
if (!is) {
printf("%d\n", i);
break;
}
}
}
return 0;
}
1542-数列
思路:模拟+哈希表
我们不难看出生成的数列如果遇到重复的,说明数列生成完成,将生成的所以数用哈希表存储,然后再遍历m寻找未存储的数
#include <stdio.h>
#include <string.h>
int main()
{
int n;
scanf("%d", &n);
while (n--) {
long long a, b, m, s = 0;
scanf("%lld%lld%lld", &a, &b, &m);
//哈希表
int mp[100001];
mp[0] = 1;
memset(mp, 0, sizeof(mp));
//遇到重复的就推出
while (!mp[(a * s + b) % m]) {
s = (a * s + b) % m;
mp[s] = 1;
}
//你也可以从1遍历到m
for (int i = 1;i <= 1e5 + 1;i++) {
if (!mp[i]) {
printf("%d\n", i);
break;
}
}
}
return 0;
}
1548-回文串
思路:你可以将每个地方数字插进去寻找规律。
例如
[
1
,
2
,
3
,
4
,
5
]
,当你插入
X
到
2
后面的时候为
[
1
,
2
,
X
,
3
,
4
,
5
]
那么要求
[
X
,
3
]
是回文串
[
1
,
2......4
,
5
]
也得是回文串
例如[1,2,3,4,5],当你插入X到2后面的时候为 \\ [1,2,X,3,4,5]那么要求[X,3]是回文串\\ [1,2......4,5]也得是回文串
例如[1,2,3,4,5],当你插入X到2后面的时候为[1,2,X,3,4,5]那么要求[X,3]是回文串[1,2......4,5]也得是回文串
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string s;
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
//取消同步流
while (cin >> s) {
int n = s.size(), ans = 0;
if (n == 1) {
cout << 2 << '\n';
continue;
}
vector<vector<bool>>mp(n + 1, vector<bool>(n + 1, false));
bool isOk = true;
for(int i = n / 2;i <= n - 2;i++) {
mp[n - 2 - i][i] = (isOk && s[i] == s[n - 2 - i]);
isOk = mp[n - 2 - i][i];
}
isOk = true;
for (int i = n / 2; i >= 1;i--) {
mp[i][n - i] = (isOk && s[i] == s[n - i]);
isOk = mp[i][n - i];
}
if (!(n & 1)) mp[n / 2 - 1][n / 2 - 1] = true;
/*for (int i = 0;i <= n;i++) {
for (int j = 0;j <= n;j++) {
cout << i << " " << j << " " << mp[i][j] << " " << '\n';
}
}*/
for (int i = 0;i <= n / 2;i++) {
int l = i - 1, r = n - i;
bool left = true, right = true;
if (l >= 0 && r >= 0 && (s[l] != s[r])) right = false;
if (i <= n / 2 - 1 && !mp[i][n - 2 - i]) left = false;
if (left && right) ans++;
else if(!right)break;
}
int m = n / 2 + 1;
if (!(n & 1)) m = n / 2;
for (int i = 1; i <= m;i++) {
int l = i - 2, r = n - i + 1;
bool left = true, right = true;
if (l >= 0 && r >= 0 && (s[l] != s[r])) right = false;
if (i <= n / 2 && !mp[i][n - i]) left = false;
if (left && right) ans++;
else if(!right)break;
}
cout << ans << '\n';
}
return 0;
}
1549-2的幂次 I
思路:二分。找到一个然后二分找第二个。
时间复杂度为
t
n
l
o
g
n
tnlogn
tnlogn
这里插一嘴,C++有二分的API,所以多用API。
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int count_pairs_with_power_of_2(vector<int>& S) {
int n = S.size();
int pairs_count = 0;
for (int i = 0; i < n; ++i) {
for (int k = 1; k <= 30; ++k) {
int target = (1 << k) - S[i];
if (target < 0) continue;
if (binary_search(S.begin() + i + 1, S.end(), target)) {
pairs_count++;
}
}
}
return pairs_count;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
vector<int> S(n);
for (int i = 0; i < n; ++i) {
scanf("%d", &S[i]);
}
printf("%d\n", count_pairs_with_power_of_2(S));
}
return 0;
}
1553-数字
太简单了No Code。
1559-奇偶数位
太简单了No Code。
1575-四位数
太简单了No Code。
1530-game
思路:先把所有的数据一次性读完然后再处理,不如你不知道哪个是最后一行。
#define _CRT_SECURE_NO_WARNINGS
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main() {
int source, game = 1, index = 0;
bool is = false;
string a, b, c, d;
vector<string>names = { "Alice", "Bob" };
vector<int>goals(2);
vector<int>sources;
vector<string>as, bs, cs, ds;
while (cin>>source>>a>>b>>c>>d) {
sources.push_back(source);
as.push_back(a);
bs.push_back(b);
cs.push_back(c);
ds.push_back(d);
}
cout << "Alice start game 1" << endl;
for (int i = 0;i < sources.size();i++) {
if (as[i] == "PAPER") sources[i] -= 5;
if (bs[i] == "PAPER") sources[i] -= 5;
if (cs[i] == "PAPER") sources[i] -= 5;
if (ds[i] == "PAPER") sources[i] -= 5;
if (sources[i] == 0) {
goals[index]++;
cout << names[index] + " win game " << game << endl;
if (i == sources.size() - 1) {
break;
}
cout << names[index] + " start game " << ++game << endl;
}
else {
index = abs(index - 1);
if (i == sources.size() - 1) {
break;
}
cout << "Change to " + names[index] << endl;
}
}
cout << "Game over " << goals[0] << ":" << goals[1] << endl;
return 0;
}
1538-打字机
思路:C++使用Vector模拟即可,还可以使用链表,我推荐用现成的Vector。
1539-区间
思路:滑动窗口。
使用滑动窗口,
L
e
f
t
和
R
i
g
h
t
,如果去掉这一个
区间还是大于
K
,那么就是区间小了,
R
i
g
h
t
右
移动
;
否则
L
e
f
t
左移查看有无更小的答案
时间复杂度
O
(
t
m
n
)
其中
m
=
26
对应
26
个字母。
使用滑动窗口,Left和Right,如果去掉这一个\\区间还是大于K,那么就是区间小了,Right右\\移动;\\否则Left左移查看有无更小的答案\\时间复杂度O(tmn)\\其中m=26对应26个字母。
使用滑动窗口,Left和Right,如果去掉这一个区间还是大于K,那么就是区间小了,Right右移动;否则Left左移查看有无更小的答案时间复杂度O(tmn)其中m=26对应26个字母。
#include <vector>
#include <limits.h>
#include <string>
#include <iostream>
using namespace std;
bool isOk(string& s, vector<int>& mp, int k) {
for (auto& m : mp) {
if (m > k) {
return false;
}
}
return true;
}
int main() {
int t = 0;
cin >> t;
while (t--) {
int k, j = 0, ans = INT_MAX;
string s;
cin >> k >> s;
vector<int>mp(26, 0);
int n = s.size();
for (auto& ss : s) {
mp[ss - 'a']++;
}
for (int i = 0;i < n;i++) {
while (j < n && !isOk(s, mp, k)) {
mp[s[j] - 'a']--;
j++;
}
if (j <= n && isOk(s, mp, k) && j >= i) {
ans = min(ans, j - i);
}
mp[s[i] - 'a']++;
}
ans = ans == INT_MAX ? 0 : ans;
cout << ans << endl;
}
return 0;
}
1541-卷积
未写
1547-圆
本来是100的通过率现在只有80了(doge
1576-分段
思路:模拟,我们可以先求出n的公因数,例如当n=16时,你能分成1,2,4,8段,然后分别求每一段的值,然后比较大小,你也可以排序之后从段最大的算起,比较段大的值肯定越小,其中 n = 1 e 5 顶天好像也就 50 还是 75 个公因数,还是能过 时间复杂度为 O ( n n l o g n ) n=1e5顶天好像也就50还是75个公因数,还是能过\\时间复杂度为O(\sqrt{n} nlogn) n=1e5顶天好像也就50还是75个公因数,还是能过时间复杂度为O(nnlogn)
#define _CRT_SECURE_NO_WARNINGS
#include <vector>
#include <algorithm>
#include <cmath>
#include <stdio.h>
using namespace std;
int main() {
long long n, sums = 0;
scanf("%lld", &n);
vector<long long>nums(n);
vector<long long>counts;
for (int i = 0;i < n;i++) {
scanf("%lld", &nums[i]);
sums += nums[i];
}
for (long long i = 1;i <= sqrt(sums)+10;i++) {
if (sums % i == 0) {
counts.push_back(i);
counts.push_back(sums / i);
}
}
sort(counts.begin(), counts.end());
for (int j = counts.size() - 1;j >= 0;j--) {
long long c = counts[j], sum = 0, p = sums / c;
bool is = true;
for (int i = 0;i < nums.size();i++) {
sum += nums[i];
if (sum == p) {
sum = 0;
}
else if (sum > p) {
is = false;
break;
}
}
if (is) {
printf("%lld\n", p);
break;
}
}
return 0;
}
1583-彩球
思路:也是滑动窗口,注意再左移右移的时候看哈希表能否满足条件即可。
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int t;
scanf("%d", &t);
while (t--) {
int m, n, k, p = 0;
scanf("%d%d%d", &n, &m, &k);
vector<int>arrs(n + 1);
vector<int>mp(n + 2, 0);
for (int i = 0;i < n;i++) {
scanf("%d", &arrs[i]);
}
arrs[n] = 0;
for (int i = 0;i < m;i++) {
if (mp[arrs[i]] == 0) {
p++;
}
mp[arrs[i]]++;
}
int left = 0, right = m - 1;
bool isOk = true;
while (right < n) {
if (p != k) {
isOk = false;
break;
}
else {
int l = arrs[left], r = arrs[right + 1];
mp[l]--;
if (mp[l] == 0) {
p--;
}
mp[r]++;
if (mp[r] == 1) {
p++;
}
left++, right++;
}
}
if (isOk) {
printf("Yes\n");
}
else {
printf("No\n");
}
}
return 0;
}
1484-刷油漆
思路:逆推,我们可以想学最后一个刷了之后,如果是列,那么前面的所有的行的颜色是不是肯定会少一个?倒数第二个如果也是和前面不同的列,那么前面的行的颜色是不是就会少两个?以此类推。
#include <cstdio>
#include <vector>
using namespace std;
int main() {
int n, m, c, t;
scanf("%d %d %d %d", &n, &m, &c, &t);
vector<bool>row(n, false), cow(m, false);
vector<int>colors(c + 1);
vector<vector<int>>operation(t, vector<int>(3));
for (int i = 0; i < t; ++i) {
for (int j = 0;j < 3;++j) {
scanf("%d", &operation[i][j]);
}
}
for (int i = t - 1;i >= 0;--i) {
if (n == 0 || m == 0) break;
int f = operation[i][0], l = operation[i][1], k = operation[i][2];
if (f == 0) {
if (!row[l - 1]) {
colors[k] += n;
m--;
row[l - 1] = true;
}
}
else {
if (!cow[l - 1]) {
colors[k] += m;
n--;
cow[l - 1] = true;
}
}
}
for (int i = 1; i <= c; ++i) {
if (colors[i] > 0) {
printf("%d %d\n", i, colors[i]);
}
}
return 0;
}
1556-和
二维前缀和的模板题,上网去学习一个什么是二位前缀和就能做了,这里不放代码。
1560-平方数
这位更是重量级。
令
x
2
+
b
x
+
c
=
(
x
+
a
)
2
化简得
x
=
a
2
−
c
b
−
2
a
令x^2+bx+c = (x+a)^2 化简得x=\frac{a^2-c}{b-2a}
令x2+bx+c=(x+a)2化简得x=b−2aa2−c
接下来就容易了,从公式不难看出,a的最大值就是
(
c
)
\sqrt(c)
(c),并且a绝对是大于0的。
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int t;
scanf("%d", &t);
while (t--) {
int b, c;
scanf("%d%d", &b, &c);
vector<int> ans;
if (4 * c == b * b) {
printf("-1\n");
continue;
}
for (int i = 1e4;i >= 0;--i) {
if ((b != 2 * i) && (i * i - c) % (b - 2 * i) == 0) {
int p = (i * i - c) / (b - 2 * i);
if (p > 0) {
//cout << i << endl;
ans.push_back(p);
}
}
}
if (ans.empty()) {
printf("0\n");
}
else {
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size() - 1; i++) {
printf("%d ", ans[i]);
}
printf("%d\n", ans.back());
}
}
return 0;
}
1567-3个矩形与1个正方形
这个也是个重量级。
思路:我们不难知道,三面积和是正方形的和,那么三个矩形的所有边肯定有一条边是正方形的边长,因此我们先找到这个矩形,然后将他作为基点,其实后面就是求剩下的两个矩形是否能组合成一个符合要求的长方形,这个长方形能和基点矩形组合成为正方形。
#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
bool compareSecond(const vector<long long>& a, const vector<long long>& b) {
return a[1] < b[1];
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
long long sum = 0;
vector<vector<long long>>grid(3, vector<long long>(2));
for (int i = 0;i < 3;i++) {
for (int j = 0;j < 2;j++) {
scanf("%lld", &grid[i][j]);
}
}
for (int i = 0;i < 3;i++) {
sum += grid[i][0] * grid[i][1];
sort(grid[i].begin(), grid[i].end());
}
sort(grid.begin(), grid.end(), compareSecond);
long long p = sqrt(sum);
if (p * p != sum) {
printf("No\n");
}
else {
long long a = grid[0][0], b = grid[0][1], c = grid[1][0], d = grid[1][1], e = grid[2][0], f = grid[2][1];
if (f == p) {
long long g = f - e;
bool is = false;
if (a == c && b + d == f && a == g) {
is = true;
}
if (a == d && a == g && b + d == f) {
is = true;
}
if (b == c && b == g && a + d == f) {
is = true;
}
if (b == d) {
if (b == f && a + c == g) {
is = true;
}
else if (b == g && a + c == f) {
is = true;
}
}
if (!is) {
printf("No\n");
}
else{
printf("Yes\n");
}
}
else {
printf("No\n");
}
}
}
return 0;
}
1578
未写
1565
未写
总结
总感觉你们的程设练习是越来越难了,当年我们的练习一都是模
拟,公式题,你们这一就开始双指针二分,还有二维前缀和,可
能也是越来越卷了吧。在oj看到刷题数排名21和22届占比最多,
我们当时都没人愿意刷ojhhhh
“请多上战场,您若长居幕后,从有一天会忘了生命之贵重”