AtCoder-abc433(A~D)
比赛链接:https://atcoder.jp/contests/abc433
A - Happy Birthday! 4
问题描述
你被给出正整数 X,Y,Z 。
高桥和爱知目前分别是 X 岁和 Y 岁。
高桥和爱知在每年的 1 月 1 日同时年龄增加 1 岁。
确定是否存在一个时刻(包括今年)高桥的年龄正好是爱知年龄的 Z 倍。
约束
1≤X,Y≤100
2≤Z≤10
所有输入值都是整数。
输入
输入按照以下格式从标准输入给出:
X Y Z
输出
如果将来有某个时刻,高桥的年龄正好是青木年龄的 Z 倍,则输出 No ,否则输出 Yes 。
样本输入 1
44 20 2
样本输出 1
Yes
四年后,高桥将是 48 岁,青木将是 24 岁,所以高桥的年龄将是青木年龄的正好两倍。因此,输出 Yes 。
示例输入 2
28 10 3
示例输出 2
No
永远不会出现高桥的年龄正好是青木年龄的三倍的时刻。因此,输出 No 。
示例输入 3
50 5 10
示例输出 3
Yes
目前,高桥的年龄正好是青木年龄的
10 倍。
注意你需要确定未来是否包括今年会有这样的时刻。
示例输入 4
1 100 2
样本输出 4
No
题解:
#include<bits/stdc++.h>
using namespace std;
int main(){
int x,y,z;
cin>>x>>y>>z;
int f=0;
for(int i=0; i<=100; i++){
if(x==y*z) {f=1; break;}
x++,y++;
}
if(f==1) cout<<"Yes";
else cout<<"No";
return 0;
}
B - Nearest Taller
问题描述
有 N 个人从左到右排成一排。从左边数第 i 个人 (1≤i≤N) 被称为第 i 个人。第 i 个人 (1≤i≤N) 的身高是 A i 。
对于每个 i=1,2,…,N ,确定是否有人在 i 的左边比 i 高,如果是,找出其中离 i 最近的人。
约束
· 1≤N≤100
· 1≤A i≤100
· 所有输入值都是整数。
输入
输入按照以下格式从标准输入给出:
N
A1 A2 … AN
输出
输出 N 行。
第 i 行 (1≤i≤N) 应包含 −1 ,如果 i 左边没有人比 i 高,否则,包含这样的人中离 i 最近的人的编号。
样本输入 1
4
4 3 2 5
样本输出 1
-1
1
2
-1
在 1 的左边没有其他人。因此,在第一行输出 −1 。
在 2 的左边的人中,只有 1 比 2 高。因此,在第二行输出 1 。
在 3 左边的人中, 1,2 比 3 高,离 3 最近的人是 2 。因此,在第三行输出 2 。
在 4 的左边没有比 4 高的人。因此,在第四行输出 −1 。
示例输入 2
3
7 7 7
示例输出 2
-1
-1
-1
可能存在多个身高相同的人。
示例输入 3
6
31 9 17 10 2 9
示例输出 3
-1
1
1
3
4
4
题解:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,a[105],b[105]={-1};
cin>>n;
for(int i=1; i<=n; i++) {cin>>a[i]; b[i]=-1;}
for(int i=1; i<=n; i++){
for(int j=i; j<=n; j++){
if(a[i]>a[j]) b[j]=i;
}
}
for(int i=1; i<=n; i++) cout<<b[i]<<" ";
return 0;
}
C - 1122 Substring 2
问题描述
你被给定一个由数字组成的字符串 S 。
如果字符串 T 满足以下所有条件,则称其为 1122-字符串。(定义与问题 F 中相同。)
· T 是一个由数字组成的非空字符串。
· ∣T∣ 是偶数,其中 ∣T∣ 表示字符串 T 的长度。
· 从 1 个字符到 ∣T∣/2 个字符的 T 中的所有字符都是相同的数字。
· 从 (∣T∣/2+1) 个字符到 ∣T∣ 个字符的 T 中的所有字符都是相同的数字。
· 将 1 加到 T 的 1 个字符的数字上得到 ∣T∣ 个字符的数字。
· 例如, 1122 、 01 和 444555 是 1122字符串,但 1222 和 90 不是 1122字符串。(人话,长度为偶数,前半段都是数字a,后半段都是数字b,且b=a+1)
找出 S 中是 1122字符串的子串的数量。
如果两个子串是从不同位置提取的,即使它们作为字符串是相同的,也会被分别计数。
约束
S 是一个由数字组成的字符串,长度在 1 和 10e6 之间(包括 1 和 10e6 )。
输入
输入按照以下格式从标准输入给出:
S
输出
输出 S 中非空且是 1122-字符串的子串的数量。
样本输入 1
1122
样本输出 1
2
以下两个子字符串满足条件。
12 从 2 到 3 的 S 个字符中提取
1122 从 1 到 4 的 S 个字符中提取
因此,输出 2 。
示例输入 2
7788788
示例输出 2
3
注意,如果从不同位置提取,即使字符串相同,两个子字符串也会被分别计数。
示例输入 3
2025
示例输出 3
0
可能不存在是 1122 字符串的子字符串。
示例输入 4
1112222334445556555
样本输出 4
11
题解:
将s分割为若干子串,每一子串只包含一个数字。例如“7788788”分为“77”、“88”、“7”、“88”四个子串。然后判断相邻子串间,后一个子串的数字是否等于前一子串数字加1,若等于,则将答案加上这两个子串中的长度最小值。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
vector<pair<char, int>> a;
char c=s[0]; // 记录子串的数字,初始化为s[0]
int cont=1; // 记录子串的长度,初始化为1
for (int i=1; i<s.length(); i++) {
if (s[i]==c) {
cont++; // 若和子串的数字相同,则子串长度加一
} else {
a.push_back({c,cont}); // 否则将该子串加入动态数组a
c=s[i]; // 更新为新的字符
cont=1; // 重置计数
}
}
a.push_back({c,cont}); // 加入最后一个子串
long long ans=0;
for (int i=0; i<a.size()-1; i++) {
int d1=a[i].first-'0';
int d2 =a[i + 1].first-'0';
if (d1+1==d2) { // 若后一子串的数字等于前一子串的数字加1,则答案加上它们长度的最小值
ans+=min(a[i].second,a[i+1].second);
}
}
cout<<ans<<endl;
return 0;
}
D - 183183
问题描述
对于正整数 x,y ,定义 f(x,y) 如下:
将 x,y 按十进制无前导零的字符串形式解释,按此顺序连接它们得到字符串 S ,然后将 S 按十进制整数形式解释所得到的值。
例如, f(12,3)=123 和 f(100,40)=10040 。
给定正整数 N,M 和一系列正整数 A=(A1 ,A2 ,…,AN ) 。
找出满足所有以下条件的整数对 (i,j) 的数量。
1≤i,j≤N
f(Ai ,A j ) 是 M 的倍数。
约束
1≤N≤2×10^5
1≤M≤10^9
1≤Ai ≤10^9
所有输入值都是整数。
输入
输入按照以下格式从标准输入给出:
N M
A1 A2 … AN
输出
输出满足所有条件的整数对 (i,j) 的数量。
样本输入 1
2 11
2 42
样本输出 1
2
当 (i,j)=(1,1) : f(A1 ,A1 )=22 是 11 的倍数。
当 (i,j)=(1,2) : f(A1 ,A2 )=242 是 11 的倍数。
当 (i,j)=(2,1) : f(A2 ,A1 )=422 不是 11 的倍数。
当 (i,j)=(2,2) : f(A2 ,A2 )=4242 不是 11 的倍数。
从以上可以看出,满足所有条件的整数对是
(i,j)=(1,1),(1,2) ,共有两对。因此,输出 2 。
示例输入 2
4 7
2 8 16 183
示例输出 2
4
示例输入 3
5 5
1000000000 1000000000 1000000000 1000000000 1000000000
示例输出 3
25
示例输入 4
12 13
80 68 862370 82217 8 56 5 168 672624 6 286057 11864
样本输出 4
10
题解:
设 Aj 的位数为 d ,则 f(Ai,Aj) = Ai * 10^d + Aj,则题目“中的f(Ai ,A j ) 是 M 的倍数”可以写为 (Ai * 10^d + Aj) ≡ 0 mod M( ≡ 为同余符号,即二者模 M 的值相等),进一步可写为 Aj ≡ - Ai * 10 ^d mod M,其中 Ai * 10^d % M = (Ai %M) * (10^9 %M)。
给出的 Ai 的位数在 1 到 10之间,则d 的取值为1 到10 。我们可以先将所有10^d %M 计算出来,存储为 Di,代表10^i %M 的值。
将输入的数组按照位数进行分组,然后遍历数组,对于Ai,计算其位数 b,在位数为b 的对应分组中去寻找满足条件:a %M * Db = Ai %M 的数的个数,将所有个数累加起来,即为最终答案。
使用哈希表来实现查找功能
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
long long m;
cin >> n >> m;
vector<long long> A(n);
for (int i = 0; i < n; i++) {
cin >> A[i];
}
// 预计算10^k % m (k=1到10)
vector<long long> pow10(11);
long long base = 10;
for (int k = 1; k <= 10; k++) {
pow10[k] = base % m;
base = (base * 10) % m;
}
// 按位数分组
unordered_map<long long, int> count_by_digit[11];
for (long long num : A) {
int digits = to_string(num).length();
long long remainder = num % m;
count_by_digit[digits][remainder]++;
}
// 统计有效对
long long ans = 0;
for (long long num : A) {
long long a_mod = num % m;
int digits_i = to_string(num).length();
for (int k = 1; k <= 10; k++) {
long long target = ((-a_mod * pow10[k]) % m + m) % m;
if (count_by_digit[k].count(target)) {
ans += count_by_digit[k][target];
}
}
}
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号