1.引言
为了更好的练习和巩固所学的知识,也会在其他OJ上找一些自己以前写过的题,供大家参考,附上链接和解答。
2.最大公约数与最小公倍数
#include<bits/stdc++.h>
using namespace std;
int GCD(int a, int b) {
if (a % b == 0)return b;
else return GCD(b, a % b);
}
int LCM(int a, int b) {
return a / GCD(a, b) * b;//这里需要注意a*b可能会超出数据范围 所以最后再乘b。
}
int main() {
int t;
cin >> t;
while (t--) {
int n,num,ans=1;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> num;
ans = LCM(ans, num);
}
cout << ans << endl;
}
return 0;
}
3.筛法和打表
PIPIOJ例题:1044.七夕节(简单)
如果单纯的枚举每一个数的因子的话,考虑到有T次查询,时间复杂度为O(T*N),会超时,所以不可取。下面给出两种常规解法:
解法1:利用筛法的思想,先求出1~N每个数的所有因子和。
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int num[N];//num[i]表示i的所有因子和
int main() {
int t;
scanf("%d",&t);
num[1] = 1;
for (int i = 1; i < N; i++) {//枚举每一个因子
for (int j = 2*i; j < N; j += i) {//包含因子i的数都加上i
num[j] += i;
}
}
while (t--) {
int n;
scanf("%d",&n);//这里注意用cin和cout的话会超时,scanf和printf比较快
printf("%d\n",num[n]);
}
return 0;
}
解法2:根号优化。对于一个数字N,只需要枚举sqrt(N)以内的因子factor,可以通过N/factor便可以得到大于等于sqrt(N)的另外一个成对的因子。这样一来时间复杂度就变为O(T*sqrt(n))。
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int main() {
int t;
scanf("%d",&t);
while (t--) {
int n,ans=1;
scanf("%d",&n);
int a=sqrt(n);
for(int i=2;i<=a;i++){
if(n%i==0){
ans+=i;
if(n/i!=i)ans+=n/i;
}
}
printf("%d\n",ans);
}
return 0;
}
4.进制转换
Leetcode例题:1017. 负二进制转换(中等)
这里的余数有三种情况:-1,1,0,但是最终的答案只有1和0,所以在余数为1时,要单独处理一下:
string baseNeg2(int n) {//用短除法,参照十进制转二进制
if(n==0)return "0";
string ans;
while(n){
int remainder = n%(-2);//余数
n = n/(-2);//商
ans += '0'+abs(remainder);//余数为负1时,由于二进制字符串只有1和0,所以将余数变为1
if(remainder<0){//余数从-1——>1,加了2,为了保持被除数不变,所以商加1,(被除数/除数=商+余数)
n+=1; // 被除数=商*除数+余数,商加1 等于余数+2(因为除数等于-2)
}
}
reverse(ans.begin(),ans.end());
return ans;
}
未完待续…