課程設計實驗報告
《c++程式設計》課程設計報告
題目一:
來源:設一
1002 Problem B
題目簡述:“水仙花數”是指一個三位數,它的各位數字的立方和等於其本身,比如:153=13+53+3^3。輸入資料有多組,每組佔一行,包括兩個整數m和n(100<=m<=n<=999)。輸出的水仙花數必須大於等於m,並且小於等於n,如果有多個,則要求從小到大排列在一行內輸出,之間用一個空格隔開;
如果給定的範圍內不存在水仙花數,則輸出no。
解題思路:判斷水仙花數,在一個迴圈裡,將區間內的每個數逐一判斷,利用餘數分離每一位數,進行判斷即可。(較簡單)
程式碼及部分說明:
#include<stdio.h>
main()
{
int m,n,i,a,b,c,s=0;
while(scanf("%d
%d",&m,&n)!=EOF)
{
for(i=m;i<=n;i++)
{
a=i/100;
b=(i%100)/10;
c=i%10;
if(aaa+bbb+ccc==i)
{
s+=1;
if(s==1)
printf("%d",i);
if(s!=1)
printf(" %d",i);
}
}
if(s==0)
printf(“no”);
printf("\n");
s=0;
}
return
0;
}
#include
using
namespace std;
int
main()
{
int m,n,i,a,b,c,s=0; while(cin>>m>>n) { if(m==0&&n&&0) break; for(i=m;i<=n;i++) { a=i/100; b=(i%100)/10; c=i%10; if(a*a*a+b*b*b+c*c*c==i)
{
s+=1;
if(s==1)
cout<<i; if(s!=1)
cout<<"
"<<i;
}
}
if(s==0)
cout<<"no";
cout<<endl;
s=0;
}
return
0;
}
對於藍色區域:輸出的格式問題:先判斷輸出資料的個數,大於一的時候先輸出一個,後面的其他資料就先輸空格,再輸資料,格式就不會出錯了。
題目二:
來源:設一
1004 Problem D
題目簡述:表示式n^2+n+41,當n在(x,y)範圍內取整數值時(包括x,y)(-39<=x<y<=50),判定該表示式的值是否都為素數。對於每個給定範圍內的取值,如果表示式的值都為素數,則輸出"OK",否則請輸出“Sorry”。
解題思路:先自定義一個函式,用來判斷素數。主函式內,藉助布林陣列判斷結果。迴圈內,每算出一個結果,就進行判斷,只有全部是素數時,藉助布林變數輸出OK即可。(較簡單)
程式碼及部分說明:
#include
#include
using
namespace std;
int prime(int
a)
{
for(int i=2;i<=sqrt(a);i++)
{
if(a%i==0)
return 0;
}
return 1;
}
int
main()
{
int x,y,m=0;
bool c[100]={true};
while(cin>>x>>y,!(x0&&y0))
{
m=0;c[1]=true;
for(int i=1;i<=100;i++)
{
m=x*x+x+41;
if(prime(m)==0)
{
c[1]=false;break;
}
if(x==y)break;x++;
}
if(c[1]==false)
cout<<“Sorry”<<endl;
elsecout<<“OK”<<endl;
}
return 0;
}
藍色部分是對每一個結果的判斷,注意要有嚴密的邏輯思維,可以先在紙演示一下。
綠色部分就是利用布林變數進行的輸出,要學會這種方法。
題目三:
來源:設一
1006 Problem F
題目簡述:定義從2開始的遞增長度為n(n<=100)的數列,按照順序每m個數求出一個平均值,如果最後不足m個,則以實際數量求平均值。程式設計輸出該平均值序列。輸入資料有多組,包含兩個正整數n和m,輸出一個平均值序列,每組輸出佔一行。
解題思路:利用while將資料輸入,先假設最後不足m個,將能正好處理的個數和剩餘資料的個數算出,利用這兩個算出的結果進行後續的平均值處理,處理過程中的情況較多,if語句的選擇就比較好用,但一定要分析全面。(一般)
程式碼及部分說明:
#include
using
namespace std;
int
main()
{
int n,m,i,j,k,sum=0,ave=1,p,q,w,e=0;
while(cin>>n>>m)
{
e=0;
p=n/m;
q=n%m;
for(i=1;i<=p;i++)
{
sum=0;
if(i==1)
{
for(j=2;j<=2*m;j+=2)
{sum+=j;}
ave=sum/m;
if(e==0)
cout<<ave;
else cout<<"
"<<ave;
e++;
w=j;
}
else
{
for(k=w;k<2*m+w;k+=2)
{sum+=k;}
ave=sum/m;
cout<<"
"<<ave;
w=k;
}
}
ave=1;
if(q==0)
{cout<<endl;}
else
{
sum=0;
for(i=w;i<q*2+w;i+=2)
{sum+=i;}
ave=sum/q;
cout<<"
"<<ave;
cout<<endl;
}
}
return 0;
}
綠色部分的處理是關鍵,有效簡便了思考過程,不過比較繁瑣。
黃色部分還是對輸出格式的處理,與第一個類似。
題目四:
來源:設一
1008 Problem H
題目簡述:有一頭母牛,它每年年初生一頭小母牛。每頭小母牛從第四個年頭開始,每年年初也生一頭小母牛。輸入資料由多個測試例項組成,每個測試例項佔一行,包括一個整數n(0<n<55),對於每個測試例項,輸出在第n年的時候母牛的數量。
解題思路:典型的斐波那契額數列變形題,先找規律,從第一個,第二個,第三個找出,可以通過遞推,迴圈即可;或者是通過陣列賦值,每一個下標對應一個數,需要時呼叫輸出即可。(難度一般)
程式碼及部分說明:
#include
using
namespace std;
int
main()
{
int n,a1=1,a2=2,a3=3,m=0;
while(cin>>n,n!=0)
{
if(n==1)
cout<<a1<<endl;
if(n==2)
cout<<a2<<endl;
if(n==3)
cout<<a3<<endl;
if(n>3)
{
m=0;a1=1;a2=2;a3=3;
for(int i=4;i<=n;i++)
{
m=a1+a3;
a1=a2;
a2=a3;
a3=m;
}
cout<<m<<endl;
}
}
return 0;
}
紅色部分是對剛開始的賦值,便於後續的計算遞推用。
綠色部分是遞推關係,值得注意的是,每次大迴圈之前一定要對前幾個值進行恢復,否則會輸出錯誤(因為會累加)。
題目五:
來源:設一
1009 Problem I
題目簡述:輸入n(n<=100)個整數,按照絕對值從大到小排序後輸出。
輸入資料有多組,每組佔一行,每行的第一個數字為n,接著是n個整數,n=0表示輸入資料的結束,不做處理。 輸出排序後的結果,兩個數之間用一個空格隔開,各佔一行。
解題思路:定義一個數組,然後直接迴圈賦值,之後用swap函式,先用if判斷大小,用abs函式,直接在swap內判斷即可,無需引入多於變數。之前用了一種比較麻煩的方法,想定義兩個陣列,a為原數,b為取絕對值之後的數,sort排序,再更換下標輸出,後來經過判斷,方法行不通,故作罷。(較簡單)
程式碼及部分說明:
#include
#include<stdlib.h>
#include
using
namespace std;
int
main()
{
int a[105],n;
while(cin>>n,!(n==0))
{
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int j=n-1;j>=1;j--)
{
for(int i=1;i<=n;i++)
{
if(i==n)
break;
if(abs(a[i])<abs(a[i+1]))
swap(a[i],a[i+1]);
}
}
for(int i=1;i<=n;i++)
{
if(i!=n)
cout<<a[i]<<"
";
if(i==n)
cout<<a[i];
}
cout<<endl;
}
return 0;
}
綠色部分為主幹部分,先判斷絕對值大小,再決定是否交換,值得學習。
題目六:
來源:設一
10013 Problem M
題目簡述:輸入一個十進位制數N,將它轉換成R進位制數輸出。包含兩個整數N(32位整數)和R(2<=R<=16,
R<>10),輸出轉換後的數,每個輸出佔一行。
解題思路:藉助函式進行操作。建構函式,與現實中相同,用幾進位制就除以幾,每一次的商正序存放在陣列中,完成後再倒序輸出。需要注意的是大於10的進位制,定義一個包含A-F的字元型陣列,if判斷如果大於十,利用迴圈輸出字母即完成工作。(一般)
程式碼及部分說明:
#include
#include<stdio.h>
#include
using
namespace std;
void
td(int n,int a);
char
ch[6]={‘A’,‘B’,‘C’,‘D’,‘E’,‘F’};
int
main()
{
int n,m;
while(scanf("%d",&n)!=EOF)
{
cin>>m;
td(n,m);
}
return 0;
}
void
td(int n,int a)
{
int
x[17],i,j,k=0;
if(n<0)
cout<<"-";
j=abs(n);
do
{
k++;
i=j%a;
j/=a;
x[k]=i;
} while(j!=0);
for(int
h=k;h>=1;h–)
{
if(x[h]<10)
cout<<x[h];
else
cout<<ch[x[h]-10];
}
cout<<endl;
}
藍色部分是除數和儲存,以便後面輸出利用。
綠色部分是自定義函式的重中之重,巧妙的構思值得大家學習與借鑑。
題目七:
來源:設一
10015 Problem O
題目簡述:求兩個集合的差,每組輸入資料佔1行,每行資料的開始是2個整數n(0<=n<=100)和m(0<=m<=100),分別表示集合A和集合B的元素個數,然後緊跟著n+m個元素,前面n個元素屬於集合A,其餘的屬於集合B. 每個元素為不超出int範圍的整數,如果n=0並且m=0表示輸入的結束,每組資料輸出一行資料,表示A-B的結果,如果結果為空集合,則輸出“NULL”,否則從小到大輸出結果。
解題思路:首先是定義兩個陣列,賦值兩個集合。然後利用雙重迴圈判斷重複的數,將其賦值為零,sort排序。最後迴圈加判斷,引入一個變數看是否為空集,輸出即可。(中等)
程式碼及部分說明:
#include
#include
int
a[105],b[105];
using
namespace std;
int
main()
{
int
m,n,i,j,k;
while(cin>>n>>m,!(n0&&m0))
{
k=0;
for(i=1;i<=n;i++)
cin>>a[i];
for(j=1;j<=m;j++)
cin>>b[j];
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(b[i]==a[j])
a[j]=0;
}
}
sort(a,a+n+1);
for(i=1;i<=n;i++)
{
if(a[i]!=0)
{
cout<<a[i]<<" ";
k++;
}
}
if(k==0)
cout<<“NULL”;
cout<<endl;
}
return 0;
}
藍色部分為作差,將相同的去除。
綠色部分為輸出且判斷是否為空集。
黃色部分利用變數看是否為空集,輸出。
題目八:
來源:設一
10016 Problem P
題目簡述:求A^B的最後三位數表示的整數。輸入資料包含多個測試例項,每個例項佔一行,由兩個正整數A和B組成(1<=A,B<=10000),如果A=0, B=0,則表示輸入資料的結束, 對於每個測試例項,請輸出A^B的最後三位表示的整數,每個輸出佔一行。
解題思路:對於一般的數可以操作,十分簡便,將後三位分離即可。而對於超記憶體的數則需要謹慎,只保留後三位即可,前面的位數一概捨去,只進行後三位的處理即可。(中等)
程式碼及部分說明:
#include
using
namespace std;
int
main()
{
long long int a,b,i;
while(cin>>a>>b,!(a0&&b0))
{
long long int s=1;
for(i=1;i<=b;i++)
s=(s*a)%1000;
cout<<s<<endl;
}
return 0;
}
紅色部分即為僅僅後三位的處理,程式碼簡單,但不太好想。
題目九:
來源:設一
10019 Problem S
題目簡述:有一隻經過訓練的蜜蜂只能爬向右側相鄰的蜂房,不能反向爬行.計算蜜蜂從蜂房a爬到蜂房b的可能路線數。蜂房的結構如下所示。
輸入資料的第一行是一個整數N,表示測試例項的個數,然後是N 行資料,每行包含兩個整數a和b(0<a<b<50)。對於每個測試例項,請輸出蜜蜂從蜂房a爬到蜂房b的可能路線數,每個例項的輸出佔一行。
解題思路:此題也是斐波那契數列變形,但要注意與之前奶牛與爬樓梯的區別,思路是自我演算出前幾項的結果,遞推時要注意迴圈的次數,比較難想,但也不困難,熟能生巧。(一般)
程式碼及部分說明:
#include
using
namespace std;
int
main()
{
long long int n,a,b,i,a1,a2,a3,m=0;
cin>>n;
while(n--)
{
cin>>a>>b;
if((b-a)==1)
cout<<“1”<<endl;
if((b-a)==2)
cout<<“2”<<endl;
if((b-a)==3)
cout<<“3”<<endl;
if((b-a)>3)
{
a1=1,a2=2,a3=3,m=0;
for(i=3;i<(b-a);i++)
{
m=a2+a3;
a2=a3;
a3=m;
}
cout<<m<<endl;
}
}
return 0;
}
藍色部分為自我演算得出的答案,需要仔細。
綠色部分為每次初始賦值和迴圈次數的判定。
題目十:
來源:設一
10022 Problem V
題目簡述:方程:Ai = (Ai-1 + Ai+1)/2 - Ci
(i = 1, 2, 3, … n),給出A0,
An+1, 和
C1, C2, …Cn.計算A1 輸入多個測試資料,對於每組資料,先是一個正整數n,(n <= 3000); 然後是2個數a0, an+1.接下來的n行每行有一個數ci(i = 1,
…n);以檔案結束符結束。對於每個測試例項,用一行輸出所求得的a1(保留2位小數)。
解題思路:對於這種數列的問題,一定要先在紙面上演算,將通項公式推出,得到規律,每一項係數的分母都為(n+1),在最後輸出的時候統一處理除(n+1)。對給出的常數係數進行迴圈處理,迴圈加和,最後減去即可。(需要數學功底,難度略大)
程式碼及部分說明:
#include
#include
using namespace
std;
int
main()
{
double a[3500],c[3500];
int n,i,j;
double b,s;
b=0.00,s=0.00;
while(cin>>n)
{
j=n;
cin>>a[0]>>a[n+1];
for(i=1;i<=n;i++)
cin>>c[i];
for(i=1;i<=n;i++)
{
s=s+j*c[i];
j--;
}
b=(n*a[0]+a[n+1]-s*2)/(n+1);
cout<<fixed<<setprecision(2)<<b<<endl;
s=0.00;
}
return 0;
}
藍色部分為對c常數部分的係數處理,迴圈累加。
綠色部分為對結果的處理,直接輸出結果即可。
題目十一:
來源:設二
1003 Problem C
題目簡述:在一個平面內有兩個點,求兩個點分別和原點的連線的夾角的大小。夾角的範圍[0,180],兩個點不會在圓心出現。輸入資料的第一行是一個數據T,表示有T組資料。每組資料有四個實數x1,y1,x2,y2分別表示兩個點的座標,這些實數的範圍是
[-10000,10000]。對於每組輸入資料,輸出夾角的大小精確到小數點後兩位。
解題思路:同樣是數學,需要用數學函式的處理,用開根號是算邊長,然後用餘弦定理算出cos夾角的值,再用反餘弦函式得到帶Π的值,但要注意的是將Π除去,再乘以180,最後保持兩位小數輸出即可。(一般)
程式碼及部分說明:
#include
#include
#include
#include
using namespace std;
int main()
{
int t,i;
double a,b,c,d,m,n,o,l,p;
cin>>t;
for(i=1;i<=t;i++)
{
cin>>a>>b>>c>>d;
m=0.00,n=0.00,o=0.00,l=0.00,p=0.00;
m=sqrt(a*a+b*b);
n=sqrt(c*c+d*d);
o=sqrt((a-c)*(a-c)+(b-d)*(b-d));
l=(m*m+n*n-o*o)/(2*m*n);
p=acos(l)*180/3.1415926;
cout<<fixed<<setprecision(2)<<p<<endl;
}
return 0;
}
藍色部分為兩點之間的距離公式。
綠色部分為餘弦定理公式。黃色部分為對結果的處理,十分關鍵,這是一細節處理。
題目十二:
來源:設二
1004 Problem D
題目簡述: 一整數,知道前幾位,不知道末二位,被另一個整數除盡了,求該數的末二位,輸入資料有若干組,每組資料包含二個整數a,b(0<a<10000,10<b<100),遇到0 0則結束。 對每組資料,將滿足條件的所有尾數在一行內輸出,同組資料的輸出,其每個尾數之間空一格,行末沒有空格。
解題思路:先將整數擴大一百倍,再除已另一個整數得餘數,後兩位從0判斷到99,但要注意個位數的輸出,前面要加零。這就需要if加判斷,這是其一;另外要注意輸出的空格處理,同樣就用if處理。最後就是if考慮的情況,一定要全面。(一般)
程式碼及部分說明:
#include
using
namespace std;
int
main()
{
int a,b,c,i,z;
while(cin>>a>>b)
{
if(a==0&&b==0)
{
break;
}
z=0;
c=a*100;
for(i=0;i<=99;i++)
{
if((c+i)%b==0)
{
z++;
if(z==1&&i>9)
cout<<i;
if(z==1&&i>=0&&i<=9)
cout<<“0”<<i;
if(z>1)
{if(i>9)
cout<<" "<<i;
if(i>=0&&i<=9)
cout<<" "<<“0”<<i;
}
}
}
cout<<endl;
}
return 0;
}
綠色部分為對空格輸出的處理,藍色部分為對輸出個位數的處理,但考慮要全面。
題目十三:
來源:設二
1005 Problem E
題目簡述: 把一個偶數拆成兩個不同素數的和,有幾種拆法。輸入包含一些正的偶數,其值不會超過10000,個數不會超過500,若遇0,則結束。對應每個偶數,輸出其拆成不同素數的個數,每個結果佔一行。
解題思路:先定義一個判斷素數函式供主函式判斷用。在利用迴圈兩邊向中間逼近,用if判斷是否符合條件輸出。(中等)
程式碼及部分說明:
#include
using namespace std;
bool prime(int n)
{
if(n2 || n3)
return 1;
if(n%6!=1 && n%6!=5)
return 0;
for( int i=5;i*i<=n;i=i+6)
{
if(n%i==0 || n%(i+2)==0)
return 0;
}
return 1;
}
int main()
{
int n,i,t;
while(cin>>n)
{
t=0;
if(n==0)
{
return 0;
}
for(i=2;i<=n/2;i++)
{
if(prime(i)==1 && prime(n-i)==1
&& i!=n-i)
t++;
}
cout<<t<<endl;
}
}
紅色部分即為兩個素數相加是否為原數的判斷,值得學習。
題目十四:
來源:設二
1006 Problem F
題目簡述:一種有趣的四位數2992,它的十進位制數表示,其四位數字之和為2+9+9+2=22,它的十六進位制數BB0,其四位數字之和也為22,同時它的十二進位制數表示1894,其四位數字之和也為22。輸入含有一些四位正整數,如果為0,則輸入結束。若n為Sky數,則輸出“#n is a Sky Number.”,否則輸出“#n
is not a Sky Number.”。
解題思路:輸入一個數,同紙上演算一樣,分別用十,十二,十六除以這個數,分別加和,然後進行比較即可。(一般)
程式碼及部分說明:
#include
using namespace std;
int main()
{
int
n,i,a,b,c,d,e,f,g,h,j;
while(cin>>n)
{
if(n==0)
break;
g=n;h=n,j=n;
a=0,b=0;
for(i=1;i<=4;i++)
{
a=n%10;
n=n/10;
b=b+a;
}
//cout<<b<<endl;
c=0,d=0;
for(i=1;i<=4;i++)
{
c=h%12;
h=h/12;
d=d+c;
}
//cout<<d<<endl;
e=0,f=0;
for(i=1;i<=4;i++)
{
e=j%16;
j=j/16;
f=f+e;
}
//cout<<f<<endl;
if(bd&&df)
cout<<g<<" is a Sky
Number."<<endl;
else cout<<g<<" is
not a Sky Number."<<endl;
}
return 0;
}
紅色部分一定要在進入迴圈之前賦0。
藍色部分即為輸入的數,由於中間有處理,故這個數需要儲存。
題目十五:
來源:設二
1008 Problem H
題目簡述:三角形,每行包含一個字元和一個整數n(0<n<41),不同的字元表示不同的花紋,整數n表示等腰三角形的高。顯然其底邊長為2n-1。如果遇到@字元,則表示所做出來的樣板三角形已經夠了。每個樣板三角形之間應空上一行,三角形的中間為空。顯然行末沒有多餘的空格。
解題思路:三角形,先判斷前一個是否輸出完一個三角形,換行。
然後利用迴圈進行三角形的輸出(與oj中矩形和菱形類似)(一般)
程式碼及部分說明:
#include
#include
using
namespace std;
int
main()
{
int n,s;
char a;
s=0;
while(cin>>a)
{
s++;
if(a=='@')
break;
else
{
cin>>n;
if(s>1)
cout<<endl;
for(int i=1;i<=n;i++)
{
for(int
j=1;j<=2*n-1;j++)
{
if(i+j==n+1||i==n||j-i==n-1)
cout<<a;
if(i+j!=n+1&&i<n&&j-i<n-1)
cout<<"
";
}
cout<<endl;
}
}
}
return 0;
}
紅色為迴圈的結束;藍色為一個三角形的輸出完了,換行;綠色三角形的輸出,加強理解即可。
總結:經過三天的程式設計實驗,一學期學到的知識得到充分的提煉和總結,運用知識的能力得到顯著提升。程式語言解決問題的方法從無到有,愈發的熟練,但還是有一些問題頭緒很亂或者是無頭緒;一方面是現實中無法用所學知識解決,從而無法用程式語言寫出;另一方面是現實中解決出來,但還不會用程式語言寫出來。對於過去的時間,所學知識還要熟練應用;以後的時間如果還想進一步提升就只能靠自學,將語言其他部分全部學會,這樣程式就會更簡單,快捷。最後,革命尚未成功,同志仍需努力。