【无标题】
GESP202603 五级
GESP202603 五级
GESP202603 五级
一. 有限不循环小数
题目描述
若 1a\frac{1}{a}a1 可化为一个有限的,不循环的小数,则称 aaa 为终止数。
请你求出在 LLL 到 RRR 中终止数的数量。
输入格式
输入一行,包含两个整数 L,RL,RL,R。
输出格式
输出一行,包含一个整数,表示 LLL 到 RRR 中终止数的数量。
输入输出样例 #1
输入 #1
2 11
输出 #1
5
说明/提示
样例解释
在 [2,11][2,11][2,11] 终止数有 222、444、555、888、101010。
数据范围
保证 1≤L≤R≤1061 \le L \le R \le 10^61≤L≤R≤106。
思路如下:
- 对于1a\frac 1aa1是一个不循环小数
(1). a=1a=1a=1,显然1a=1\frac 1a=1a1=1。
(2). a>=2a>=2a>=2,若1a\frac1aa1是有限小数,即存在正整数kkk使得
1a=N10k,(N∈Z+)\frac 1a=\frac N{10^k},(N∈Z^+)a1=10kN,(N∈Z+)
即:
10k=a∗N10^k=a * N10k=a∗N
即:
a∣10ka \mid 10^ka∣10k
即:
a∣2k∗5ka \mid 2^k*5^ka∣2k∗5k
由算术基本定理可知:
a=p1α1∗p2α2∗...∗pkαk(a>1,pi∈P)a = p_1^{\alpha_1} * p_2^{\alpha_2} *... * p_k^{\alpha_k} (a > 1, p_i \in P)a=p1α1∗p2α2∗...∗pkαk(a>1,pi∈P)
即:
p1α1∗p2α2∗...∗pkαk∣2k∗5kp_1^{\alpha_1} * p_2^{\alpha_2} *... * p_k^{\alpha_k} \mid 2^k*5^kp1α1∗p2α2∗...∗pkαk∣2k∗5k
显然,aaa中必然只能包含质因子222或者555
解法1(质因数分解)
步骤
- 枚举iii从LLL到RRR
- 将iii进行质因数分解,检查是否存在 222 和 555 以外的质因子。
时间复杂度O(RRO(R \sqrt RO(RR)
#include <bits/stdc++.h>
using namespace std;
bool fac(int n) {
for (int i = 2; i <= sqrt(n); i++) {
while (n % i == 0) {
n /= i;
if (i != 2 && i != 5) return false;
}
}
if (n > 1 && n != 2 && n != 5) return false;
return true;
}
int main() {
int L, R, ans = 0;
cin >> L >> R;
for (int i = L; i <= R; i++) {
if (fac(i)) ++ans;
}
cout << ans << endl;
return 0;
}
解法2(直接分解222和555)
步骤
- 枚举iii从LLL到RRR
- 由于我们已经证明出iii中只能包含222和555质因子,可以直接从i中分解所有的222和555,判断最后是否为1。
时间复杂度O(RlogRO(R log RO(RlogR)
#include <bits/stdc++.h>
using namespace std;
bool fac(int n) {
while (n % 2 == 0) n /= 2;
while (n % 5 == 0) n /= 5;
return n == 1;
}
int main() {
int L, R, ans = 0;
cin >> L >> R;
for (int i = L; i <= R; i++) {
if (fac(i)) ++ans;
}
cout << ans << endl;
return 0;
}
解法3(构造法)
由于终止数只能包含质因子 222 和 555,因此所有终止数均为形如 2x∗5y2^x * 5^y2x∗5y 的数(x,y≥0x, y \ge 0x,y≥0)。我们可以直接枚举不超过 RRR 的此类数,统计落在 [L,R][L, R][L,R] 内的个数。
时间复杂度为 O(log2R×log5R)O(\log_2 R \times \log_5 R)O(log2R×log5R),远优于 O(RlogR)O(RlogR)O(RlogR) 的枚举方法。
#include <bits/stdc++.h>
using namespace std;
int main() {
int L, R, ans = 0;
cin >> L >> R;
for (int x = 1; x <= R; x *= 2) { // 枚举 2 的幂
for (int y = x; y <= R; y *= 5) { // 在 2 的幂基础上乘 5 的幂
if (y >= L) ans++;
}
}
cout << ans << endl;
return 0;
}
二. 找数
题目描述
给定一个包含 nnn 个互不相同的正整数的数组 AAA 与一个包含 mmm 个互不相同的正整数的数组 BBB,请你帮忙计算有多少个数在数组 AAA 与数组 BBB 中均出现。
输入格式
第一行包含两个整数 n,mn,mn,m。
第二行包含 nnn 个正整数 a1,a2,⋯ ,ana_1,a_2,\cdots,a_na1,a2,⋯,an 表示数组 AAA。
第三行包含 mmm 个正整数 b1,b2,⋯ ,bmb_1,b_2,\cdots,b_mb1,b2,⋯,bm 表示数组 BBB。
输出格式
输出一个整数,表示在数组 AAA 与数组 BBB 中均出现的数的个数。
输入输出样例 #1
输入 #1
3 5
4 2 3
3 1 5 4 6
输出 #1
2
说明/提示
样例解释
样例 1 中,444、333 在数组 AAA 与 BBB 中均出现。
数据范围
对于 40%40\%40% 的数据,保证 1≤n,m≤10001 \leq n,m \leq 10001≤n,m≤1000。
对于 100%100\%100% 的数据,保证 1≤n,m≤1051 \leq n,m \leq 10^51≤n,m≤105,1≤ai,bi≤1091 \leq a_i,b_i \leq 10^91≤ai,bi≤109。
解法1(map或者哈希)
思路:
- 将数组aaa中数据存入map容器。
- 遍历数组 bbb,判断当前元素是否在容器中,若是则计数加一。
map的时间复杂度O((m+n)logn)O((m+n)logn)O((m+n)logn),哈希时间复杂度O(m+n)O(m+n)O(m+n)
注意:由于1≤ai,bi≤109,直接使用桶,空间上无法接受,可以使用map或者unordered_map\color{red}注意:由于 {1 \leq a_i, b_i \leq 10^9}, 直接使用桶,空间上无法接受,可以使用map或者unordered\_map注意:由于1≤ai,bi≤109,直接使用桶,空间上无法接受,可以使用map或者unordered_map
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
map<int, int> mp;
unordered_map<int, int> mp2;
int main() {
int x, n, m, ans = 0;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> x;
mp[x]++;
}
for (int i = 1; i <= m; i++) {
cin >> x;
if (mp[x]) ans++;
}
cout << ans << endl;
return 0;
}
解法2(排序+二分查找)
思路:
- 将aaa数组进行排序
- 遍历数组 bbb,对每个元素在 aaa 中二分查找是否存在。。
时间复杂度O(nlogn)O(nlogn)O(nlogn)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int a[N];
int main() {
int x, n, m, ans = 0;
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
sort(a + 1, a + n + 1);
for (int i = 1; i <= m; i++) {
cin >> x;
// 使用binary_search函数判断x是否存在
if (binary_search(a, a + n + 1, x)) ++ans;
// 使用lower_bound定位大于等于x位置
//if (*lower_bound(a + 1, a + n + 1, x) == x) ++ans;
}
cout << ans << endl;
return 0;
}
解法3(排序+双指针)
思路:
- 将aaa数组和bbb数组进行排序
- 使用双指针同时遍历两个有序数组,统计相同元素个数。
时间复杂度O(nlogn)O(nlogn)O(nlogn)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int a[N], b[N];
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= m; i++) cin >> b[i];
sort(a + 1, a + n + 1);
sort(b + 1, b + m + 1);
int i = 1, j = 1, ans = 0;
while (i <= n && j <= m) {
if (a[i] == b[j]) { // 相等计数
ans++;
i++;
j++;
} else if (a[i] < b[j]) { // a小,a往尝试
i++;
} else { // b小,b往后尝试
j++;
}
}
cout << ans << endl;
return 0;
}
更多推荐



所有评论(0)