总结
- 这一年前6题简单,25min做完,卡在了第七题、第八题都没AC。
- 第三题在声明局部变量、输出时类型转换用的时间多了点。能放全局的就放全局,能double就不用int。
- 第五题题意读错了,时间花多了。
第七题
20min 12/20
题意
给两个整数n、k。求n的阶乘去掉末尾0后的k位数,要求补上前导零。同时输出末尾0的个数。
思路
- 首先n上限是1E7,且k最大为9。则求阶乘时必须用long long。
- 然后,为方便取前k为数,设置mod = pow(10, k)。
- 每次循环把2和5的因子存起来,乘出来后取模。
- 最后乘上所有的2和5.
小结
这里注意错解中,直接相乘可能由于某一连续区间,5的因子过多而2的因子过少,导致0过多从而丢失精度。
题解 - 待测试
#include<bits/stdc++.h>
using namespace std;
#define int long long
string b;
int n, k, cnt, ans = 1, mod, tmp, c2, c5;
signed main(){
cin>>n>>k;
mod = pow(10, k);
for(int i = 2; i <= n; i ++){
int tar = i;
while(tar % 5 == 0){
tar /= 5;
c5 ++;
}
while(tar % 2 == 0){
tar /= 2;
c2 ++;
}
ans = (ans * tar) % mod;
}
int c = min(c2, c5);
for(int i = 0; i < c2 - c; i ++) ans = (ans * 2) % mod;
for(int i = 0; i < c5 - c; i ++) ans = (ans * 5) % mod;
b = to_string(ans);
while(b.size() < k) b = "0" + b;
cout<<b<<' '<<c;
return 0;
}
错解
#include<bits/stdc++.h>
using namespace std;
#define int long long
string b;
signed main(){
int n, k, tmp, cnt = 0, ans = 1;
cin>>n>>k;
for(int i = 2; i <= n; i ++){
ans *= i;
while(ans % 10 == 0){
ans /= 10;
cnt++;
}
b = to_string(ans);
if(b.size() > k) b = b.substr(b.size() - k);
ans = stoi(b);
}
while(b.size() < k)b = "0" + b;
cout<<b<<' '<<cnt;
return 0;
}
第八题 - 二分查找
15min 16/25
题意
给定数组大小n和一个数字p,然后给出n个数字的集合。
从集合中取2个数字,能和p一起构成三角形,问这样的组合数。
思路
暴力两层循环能拿16分:
- 先得到数组rec
- sort排序使rec从小到大
- 然后ij指针两层循环。每次判断三个数字能否构成三角形。
二分AC: - 同样先得到rec并排好序。
- rec最后插入一个无穷大INT_MAX以简化后续二分逻辑。
- 然后指针i遍历rec,
- 分别求出
rec[i]
和p构成三角形的第三条边上下限minl、maxl。 - 二分查找第一个大于minl的数字,大于等于maxl的数字,maxl - minl表示对于下标i可以组成的组合数。
- 分别求出
小结
- 网上看到一个求二分的函数记录一下:
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
- 二分法不熟悉,TLE后转改二分没改完就到时间了。
//求右侧性质最左端:
int l = i + 1, r = n;
while(l < r){
int m = l + r >> 1;
if(右侧性质成立) r = m;
else l = m + 1;
}
//求左侧性质最右端:
int l = i + 1, r = n;
while(l < r){
int m = l + r + 1 >> 1;
if(左侧性质成立) l = m;
else r = m - 1;
}
- 注意cnt需要开longlong,比如100000个元素包括q全是1,总数cnt会超过INT_MAX。
题解 - AC
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n, p, cnt, rec[100100];
signed main(){
cin>>n>>p;
for(int i = 0; i < n; i ++) cin>>rec[i];
sort(rec, rec + n);
for(int i = 0; i < n; i ++)
cnt += lower_bound(rec + i + 1, rec + n, rec[i] + p) - upper_bound(rec + i + 1, rec + n, abs(rec[i] - p));
cout<<cnt;
return 0;
}
题解 - 待测试
#include<bits/stdc++.h>
using namespace std;
int rec[100010];
int main(){
int n, p; cin>>n>>p;
for(int i = 0; i < n; i ++) scanf("%d", &rec[i]);
sort(rec, rec + n);
rec[n] = INT_MAX;
int cnt = 0;
for(int i = 0; i < n - 1; i ++){
int minl = abs(rec[i] - p), maxl = rec[i] + p;
int l = i + 1, r = n, al, ar;
while(l < r){
int m = l + r >> 1;
if(rec[m] > minl) r = m;
else l = m + 1;
}
al = r;
l = i + 1, r = n;
while(l < r){
int m = l + r >> 1;
if(rec[m] >= maxl) r = m;
else l = m + 1;
}
ar = r;
cnt += ar - al;
}
cout<<cnt;
return 0;
}
第一题
1min
#include<bits/stdc++.h>
using namespace std;
int main(){
double a, b, x;
cin>>a>>b;
x = a / b;
printf("%.0lf/%.1lf=%.0lf", a, x, b);
return 0;
}
第二题
1min
#include<bits/stdc++.h>
using namespace std;
int main(){
int n; cin>>n;
if(n >= 90) printf("gong xi ni kao le %d fen!", n);
else printf("kao le %d fen bie xie qi!", n);
return 0;
}
第三题
5min
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, a, b, l = 0, r = 0, all = 0, man = 0;
cin>>n;
for(int i = 0; i < n; i ++){
cin>>a>>b;
all += b;
if(a == 1){
l += b;
man++;
}else r += b;
}
if(n != man && man != 0) printf("%.1lf %.1lf %.1lf",(double)all / n, (double)l / man, (double)r / (n - man));
else if(n == man) printf("%.1lf %.1lf X",(double)all / n, (double)l / n);
else printf("%.1lf X %.1lf",(double)all / n, (double)r / n);
return 0;
}
第四题
1min
#include<bits/stdc++.h>
using namespace std;
int main(){
long long a, b;
cin>>a>>b;
a = a + b;
string c = to_string(a);
for(int i = 0; i < c.size(); i ++)
cout<<c[i]<<endl;
return 0;
}
第五题
7min
#include<bits/stdc++.h>
using namespace std;
int main(){
string ans, g; cin>>ans>>g;
while(g != "-1"){
if(g.size() != ans.size()) puts("No");
else{
int sum = 0, f = 1;
for(int i = 0; i < ans.size(); i ++){
if(ans[i] != g[i]){
sum ++;
if(abs(ans[i] - g[i]) > 1) f = 0;
}
}
if(sum > 1) f = 0;
puts(f ? "Yes":"No");
}
cin>>g;
}
return 0;
}
第六题
8min
#include<bits/stdc++.h>
using namespace std;
vector<int> l(10);
int n, tmp, ptr, t;
string s[3] = {"ChuiZi", "JianDao", "Bu"};
int main(){
cin>>n;
for(int i = 0; i < n; i ++) cin>>l[i];
string a, b;
cin>>a;
t = l.front();
while(a != "End"){
if(t != 0){
for(int i = 0; i < 3; i ++)
if(a == s[i]) cout<<s[(i + 2) % 3]<<endl;
t--;
}else{
for(int i = 0; i < 3; i ++)
if(a == s[i]) cout<<s[(i + 1) % 3]<<endl;
ptr = (ptr + 1) % n;
t = l[ptr];
}
cin>>a;
}
return 0;
}