简单题集锦
HJ108 求最小公倍数
题目:https://www.nowcoder.com/practice/22948c2cad484e0291350abad86136c3?tpId=37&tqId=21331&rp=1&ru=/exam/oj/ta&qru=/exam/oj/ta&sourceUrl=%2Fexam%2Foj%2Fta%3FtpId%3D37&difficulty=undefined&judgeStatus=undefined&tags=&title=
复习一下辗转相除法:
原理证明
设两数为a、b(a>b),用gcd(a,b)表示a,b的最大公约数,r=a (mod b) 为a除以b的余数,k为a除以b的商,即a÷b=kr。辗转相除法即是要证明gcd(a,b)=gcd(b,r)。
第一步:令c=gcd(a,b),则设a=mc,b=nc
第二步:根据前提可知r =a-kb=mc-knc=(m-kn)c
第三步:根据第二步结果可知c也是r的因数
第四步:可以断定m-kn与n互质(假设m-kn=xd,n=yd (d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)cd,b=nc=ycd,则a与b的一个公约数cd>c,故c非a与b的最大公约数,与前面结论矛盾),因此c也是b与r的最大公约数。
从而可知gcd(b,r)=c,继而gcd(a,b)=gcd(b,r)。
证毕。
以上步骤的操作是建立在刚开始时r≠0的基础之上的。即m与n亦互质。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a,b; 4 int gcd(int a,int b){ 5 if(b) return gcd(b,a%b); 6 else return a; 7 } 8 int main(){ 9 cin>>a>>b; 10 cout<<a*b/gcd(a,b); 11 return 0; 12 }
HJ107 求解立方根
题目:https://www.nowcoder.com/practice/caf35ae421194a1090c22fe223357dca?tpId=37&tqId=21330&rp=1&ru=/exam/oj/ta&qru=/exam/oj/ta&sourceUrl=%2Fexam%2Foj%2Fta%3FtpId%3D37&difficulty=undefined&judgeStatus=undefined&tags=&title=
不让用库函数,那就显然是二分。几乎没怎么写过小数二分,差点给我写老实了=。=幸好还是简单
因为三次方只在[0,+∞]上满足单调性,就分成正负两种情况处理。
然后要注意 l 和 r 的范围,一个数的三次方不一定比它本身大。
1 #include<bits/stdc++.h> 2 using namespace std; 3 double n,l,r,mid; 4 int main(){ 5 cin>>n; 6 bool f=0; 7 if(n<0){ 8 n=-n; 9 f=1; 10 } 11 l=0;r=100; 12 while(l<=r){ 13 mid=(l+r)/2; 14 if(mid*mid*mid<=n){ 15 l=mid+0.01; 16 } 17 else{ 18 r=mid-0.01; 19 } 20 } 21 if(f) mid=-mid; 22 printf("%.1lf",mid); 23 return 0; 24 }
HJ106 字符逆序
题目:https://www.nowcoder.com/practice/cc57022cb4194697ac30bcb566aeb47b?tpId=37&tqId=21329&rp=1&ru=/exam/oj/ta&qru=/exam/oj/ta&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D3%26tpId%3D37%26type%3D37&difficulty=undefined&judgeStatus=undefined&tags=&title=
就当作练一下输入。
简简单单的,很安心=v=
1 #include<bits/stdc++.h> 2 using namespace std; 3 int len=0,st[10010]; 4 void init(){ 5 char c=getchar(); 6 while(c!='\n'){ 7 st[len++]=c; 8 c=getchar(); 9 } 10 return; 11 } 12 int main(){ 13 init(); 14 for(int i=len-1;i>=0;i--) 15 printf("%c",st[i]); 16 return 0; 17 }
HJ103 Redraiment的走法
题目:https://www.nowcoder.com/practice/24e6243b9f0446b081b1d6d32f2aa3aa?tpId=37&tqId=21326&rp=1&ru=/exam/oj/ta&qru=/exam/oj/ta&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D3%26tpId%3D37%26type%3D37&difficulty=undefined&judgeStatus=undefined&tags=&title=
一个简单得很安心的最长上升子序列,n甚至只有200
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a[220],dp[220],ans; 4 int main(){ 5 cin>>n; 6 for(int i=1;i<=n;i++) 7 cin>>a[i]; 8 for(int i=1;i<=n;i++) dp[i]=1; 9 for(int i=2;i<=n;i++){ 10 for(int j=1;j<i;j++) 11 if(a[j]<a[i])dp[i]=max(dp[i],dp[j]+1); 12 } 13 ans=1; 14 for(int i=1;i<=n;i++) 15 ans=max(ans,dp[i]); 16 cout<<ans; 17 return 0; 18 }
然后我就思考了一下nlogn的做法
就是维护一个b[k]数组记录截至当前位置为止,满足长度为k的上升子序列的最小的a[i]值。
然后二分进行判断,顺便一直维护b[k]数组保持值最小就好啦。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 int n,a[maxn],b[maxn],c[maxn],ans=1; 5 int Ef(int x){ 6 int l,r,mid; 7 l=1;r=ans; 8 while(l<=r){ 9 mid=(l+r)/2; 10 if(x>b[mid])l=mid+1; 11 else r=mid-1; 12 } 13 return l; 14 } 15 int main(){ 16 cin>>n; 17 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 18 for(int i=1;i<=n;i++) c[i]=1; 19 b[1]=a[1]; 20 for(int i=2;i<=n;i++){ 21 b[1]=min(b[1],a[i]); 22 int t=Ef(a[i]); 23 if(t>ans) b[++ans]=a[i]; 24 b[t]=min(b[t],a[i]); 25 } 26 cout<<ans; 27 return 0; 28 }
感觉自己语言能力好捉急呀。。。。思路讲的不太好,但是难以把抽象的东西表达清楚…无奈
今晚随便写了QQ音乐的笔试,又被核心代码模式恶心得不清,还迟到了二十多分钟入场= 。=
不管了,继续刷题,华为我来噜> <!