Day one
遞迴求解最大公約數
//遞迴求解最大公約數
#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!