递归求解最大公约数
//递归求解最大公约数
#include<iostream>
using namespace std;
/*int gcd(int a,int b){ //老办法
int t,r;
if(a < b){
t = a;
a = b;
b = t;
}
if(b == 0){
return a;
}
r = a%b;
while(r != 0){
a = b;
b = r;
r = a%b;
}
return b;
}
int gcd(int a,int b){
if(a%b == 0){
return b;
}
else{
return gcd(b,a%b);
}
}
*/
int gcd(int a,int b){ //炒鸡简单的递归
return a == 0?b:gcd(b%a,a);
}
int main(){
int x,y,t;
cin>>x>>y;
cout<<gcd(x,y)<<endl;
return 0;
}
前缀和思想求解数组从x到y之间的数值的和
讲的是预处理的前缀和思想
#include<iostream>
using namespace std;
const int N = 6; //数组元素个数
int main(){
int a[N],x,y,sum[N],total;
for(int i = 0;i < N;i++){ //输入数组元素
cin>>a[i];
}
sum[0] = a[0];
for(i = 1;i < N;i++){ //对数组元素预处理,sum[i]为数组元素前i项之和
sum[i] = sum[i-1]+a[i];
}
cin>>x>>y;
if(x == 1){
total = sum[y-1];
}
else{
total = sum[y-1]-sum[x-2];
}
cout<<total<<endl;
return 0;
}
还是前缀和思想
#include<iostream>
using namespace std;
int main(){
int n,m;
cin>>n>>m; //n为数组元素个数,m为求区间和的次数
int *a = new int[n]; //动态分配数组大小
int *sum = new int[n];
int *total = new int[m];
int *x = new int[m];
int *y = new int[m];
for(int i = 0;i < n;i++){ //输入数组元素
cin>>a[i];
}
for(int j = 0;j < m;j++){ //每行输入两个整数Xi,Yi
cin>>x[j]>>y[j];
}
sum[0] = a[0];
for(i = 1;i < n;i++){ //对数组元素预处理,sum[i]为数组元素前i项之和
sum[i] = sum[i-1]+a[i];
}
for(j = 0;j < m;j++){ //输出m行,每行输出一个整数,表示a[Xi]+a[Xi+1]+...+a[Yi]
if(x[j] == 1){
total[j] = sum[y[j]-1];
}
else{
total[j] = sum[y[j]-1]-sum[x[j]-2];
}
cout<<total[j]<<endl;
}
delete[] a;
delete[] sum;
delete[] total;
delete[] x;
delete[] y;
return 0;
}
以下是改进版,使用vector动态分配数组,而不是用指针,可以避免指针用完之后忘记detele的错误
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n,m;
cin>>n>>m; //n为数组元素个数,m为求区间和的次数
vector<int> a = new int[n]; //动态分配数组大小
vector<int> sum = new int[n];
vector<int> total = new int[n];
vector<int> x = new int[n];
vector<int> y = new int[n];
for(int i = 0;i < n;i++){ //输入数组元素
cin>>a[i];
}
for(int j = 0;j < m;j++){ //每行输入两个整数Xi,Yi
cin>>x[j]>>y[j];
}
sum[0] = a[0];
for(i = 1;i < n;i++){ //对数组元素预处理,sum[i]为数组元素前i项之和
sum[i] = sum[i-1]+a[i];
}
for(j = 0;j < m;j++){ //输出m行,每行输出一个整数,表示a[Xi]+a[Xi+1]+...+a[Yi]
if(x[j] == 1){
total[j] = sum[y[j]-1];
}
else{
total[j] = sum[y[j]-1]-sum[x[j]-2];
}
cout<<total[j]<<endl;
}
return 0;
}
Least common multiple (LCM)
http://acm.hdu.edu.cn/showproblem.php?pid=1019
The least common multiple (LCM) of a set of positive integers is the smallest positive integer which is divisible by all the numbers in the set. For example, the LCM of 5, 7 and 15 is 105.
Input
Input will consist of multiple problem instances. The first line of the input will contain a single integer indicating the number of problem instances. Each instance will consist of a single line of the form m n1 n2 n3 … nm where m is the number of integers in the set and n1 … nm are the integers. All integers will be positive and lie within the range of a 32-bit integer.Output
For each problem instance, output a single line containing the corresponding LCM. All results will lie in the range of a 32-bit integer.Sample Input
2
3 5 7 15
6 4 10296 936 1287 792 1Sample Output
105
10296最小公倍数(LCM)的一个正整数集是最小的正整数的集合中的所有数整除。
输入
输入将包括多个问题实例。输入的第一行将包含一个整数,该整数表示问题实例的数量。
输出
每个问题的实例,输出一行,包含相应的模块。所有的结果将位于一个32位整数的范围内。
炒鸡简单的题,应该最开始学C就练过的题,竟然把我弄得真的特别想哭,还是欲哭无泪的那种
以下分别是我弄过的n个最终提交的版本
首先1.0:看上去也特别简单,就是先求两个数的最大公约数,在两个数相乘除以最大公约数即是最小公倍数。这时候我还没注意到数据范围,依然是先乘再除,但是这里有在后面改过来了
#include<stdio.h>
int gcd(int a,int b){ //求两个整数的最大公约数
int t,r;
if(a < b){
t = a;
a = b;
b = t;
}
if(b == 0){
return a;
}
r = a%b;
while(r != 0){
a = b;
b = r;
r = a%b;
}
return b;
}
int lcm(int a,int b){ //求两个整数的最小公倍数
return a/gcd(a,b)*b;
}
int main(){
int n,x,i,r;
scanf("%d",&n); //多个问题实例的个数
for(i = 0;i < n;i++){
r = 1;
do{
scanf("%d",&x);
r = lcm(r,x); //r为前j个整数与第j+1个整数的最小公倍数
}while(getchar() != '\n');
printf("%d\n",r);
}
return 0;
}
这里是1.1:应该是已经错误了很多次花了很多很多时间一个上午没弄出来,下午又接着弄,弄着弄着放弃了接着晚上又来弄才出来的版本吧,因为显示超时,就把两个函数整合在一块了
int lcm(int m, int n){
int t,i = n,j = m;
while ((m%n)!=0){
t = n;
n = m % n;
m = t;
}
return i/n*j;
}
*不说废话,直接上1.2。不过还是超时
#include <stdio.h>
int gcd(int a,int b){
return a == 0?b:gcd(b%a,a);
}
int lcm(int a,int b){ //求两个整数的最小公倍数
return a/gcd(a,b)*b;
}
int main(){
int n,x,i,r;
scanf("%d",&n); //多个问题实例的个数
for(i = 0;i < n;i++){
r = 1;
do{
scanf("%d",&x);
r = lcm(r,x); //r为前j个整数与第j+1个整数的最小公倍数
}while(getchar() != '\n');
printf("%d\n",r);
}
return 0;
}
AC通过的最终版本。好像是说多次函数调用需要很大的时间开销,就把求最小公倍数的函数放在主函数内了。这道题通过的时候真的特别松了一口气,特别开心。虽然说在这么简单的一道题上耗了这么久真的很弱很弱,但是就好像你在攀登的过程中即使落后于大部队,但是你还是终于看到了山腰的美景,这个过程越是艰难,你所获得的成绩感也就越多。这道题的小总结就是也算通过这道题熟悉了代码提交的系统,因为这个过程中一度怀疑是我的编译器或者电脑的毛病,幸好没有放弃
#include<stdio.h>
int gcd(int a,int b){
if(b == 0){
return a;
}
return gcd(b,a%b);
}
int main(){
int T;
int n,a,b,i;
int cnt;
scanf("%u",&T);
while(T--){
scanf("%d",&n);
cnt = a = 1;
for(i = 1;i <= n;i++){
scanf("%d",&b);
cnt = a/gcd(a,b)*b;//换一下,先除后乘,免得数据溢出
a = cnt;
}
printf("%d\n",cnt);
}
return 0;
}
B - 进制转换
http://acm.hdu.edu.cn/showproblem.php?pid=2031
输入一个十进制数N,将它转换成R进制数输出。
Input
输入数据包含多个测试实例,每个测试实例包含两个整数N(32位整数)和R(2<=R<=16, R<>10)。
Output
为每个测试实例输出转换后的数,每个输出占一行。如果R大于10,则对应的数字规则参考16进制(比如,10用A表示,等等)。
Sample Input
7 2
23 12
-4 3
Sample Output
111
1B
-11
这道题也比较曲折。看代码吧
#include <stdio.h>
#include <stdlib.h>
int main(){
char str[8],N[20],R[20];
int n,r;
int count = 0;
while(scanf("%d%d",&n,&r)!=EOF){//输入每个测试实例,包含两个整数N(32位整数)和R(2<=R<=16, R<>10)
N[count] = n;
R[count] = r;
count++;
}
for(int i = 0;i < count;i++){
itoa(n,str,i); //用函数转换itoa(值,数组名,进制)
printf("%s\n",str);
}
return 0;
}
#include<stdio.h>
int k = 0; //用来记录每一个进制存放的位置
char str[20]; //用来存放每一个进制的数
int N[20],R[20];
void f(int n,int r){
if(n == 0)
return;
f(n/r,r);
str[k++] = n%r;
}
int main(){
int n,r;
int count = 0;
while(scanf("%d%d",&n,&r)!=EOF){//输入每个测试实例,包含两个整数N(32位整数)和R(2<=R<=16, R<>10)
N[count] = n;
R[count] = r;
count++;
}
for(int i = 0;i < count;i++){
if(N[i] < 0){
N[i] = -N[i];
printf("-");
}
f(N[i],R[i]);
for(int j = 0;j < k;j++){
if(str[j] < 10)
printf("%d",str[j]);
else
printf("%c",str[j]+'A'-10);
}
printf("\n");
k = 0;
}
return 0;
}
小总结:第一天属于对整个过程都非常陌生,自己真的特别特别弱,对比于那些大神,不要去过于追求练题的数量,要把做过的每一道题都给弄懂,另外还有很多很多需要学习和掌握的东西。Fighting!