CSU20屆2020年期中考試試題題解
一 .關于CSU期中考試最后一題階乘找零的一丟丟討論🤣🤣:
(撰稿人 brainstormYYF)
題目描述
小帥接到一個任務,就是要找出一個整數n!中末尾到底有多少個0,請你幫幫他,
輸入
多組樣例,輸入一個整數n(n≤10000)
輸出
對于每一個輸入的n,輸出一個結果,每個輸出占一行,
樣例輸入 Copy
5
16
27
樣例輸出 Copy
1
3
6
我首先看這道題,當然就按題目的思路一步步想,它讓階乘,我就階乘,說啥干啥嘛,不過注意到整數n的范圍是n<=10000,那當然直接求n的階乘是相當不現實的,計算機是無法儲存那么大的數的
那么第一種方法明顯就是解決大數的處理
int型別的資料儲存大小是四個位元組,儲存的資料范圍是-2,147,483,648 到2,147,483,647,unsigned int型別的資料在二進制中中的儲存形式是沒有符號位的,所以unsigned的資料范圍是0到 4,294,967,295(2,147,483,647的2倍加1),即使是long long int 型別的資料是64位的(同理unsigned long long int類比unsigned int),也是遠遠不夠算n的階乘的,那當然要考慮的就是如何解決資料超限的程序,
要解決資料超限的問題,那當然想到的就是將階乘的程序分開,一步一步做乘法,每次進行乘法后就想方設法化簡數,
int sum=0;
int num=n;
for(int i=n-1;i>=1;i--)
{
num=num*i;
while(num%10==0&&num!=0)
{
sum++;
num=num/10;
}
num=num%1000;
}
這就是這道題的核心代碼!!!!
核心要點:
1.將階乘的程序用for回圈表示出來,
2.在每次回圈后記錄末尾零的個數(當末尾出現零時,零乘以任何數均為零,所以末尾出現零,即不會改變)此時進行記錄零的個數并消掉末尾零,消掉末尾的零并不會對以后末尾零的增加個數有任何影響,
3.此時還要進行大數的化簡 ,保證中間大數不會超過資料的儲存范圍,因為我要求的是末尾零的個數,而大數的首部對末尾零的個數不會有影響,所以我就選擇了進行取余運算,取出末尾的部分就中了,當然不能只取最后一位,舉個例子,4|25=100,而最后一位54=20,少了個零,所以大數的末尾若干位都對最后零的個數有影響,而n的取值范圍為小于10000,即對10000取余是比較保險的選擇,實際上我當時考試時對1000取余就通過了,對100取余AC40%,對10取余則只有可憐兮兮的AC%20啦,
最后附上完整代碼:
#include<stdio.h>
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int sum=0;
int num=n;
for(int i=n-1;i>=1;i--)
{
num=num*i;
while(num%10==0&&num!=0)
{
sum++;
num=num/10;
}
num=num%1000;
}
printf("%d\n",sum);
}
// getchar();getchar();
return 0;
}
此種寫法應該說是簡潔明了的處理大數的方法,c或c++處理大數的方法一般有兩種,這道題用到的巧化簡,還有就是用字串,
<如果你覺得這道題用第一種方法理解有難度,不想考慮這么多超限的問題,那當然這道題還有第二種解決方法>
第二種解決方法的思路即是看階乘中的每個因數,將每個因數單獨拿出看,每個因數即決定了末尾會出現多少個零
那么這個的關鍵就變成了單獨研究每個數,而每個數的關鍵又是找5,當然找10和2也可,不過就增加了代碼復雜度,我們力求代碼的簡潔明了易懂!!!!這點十分重要!!!!!😎😎
#include<stdio.h>
int main(){
int n;
while(scanf("%d",&n)!=EOF){
int ans=0;
int j;
for(int i=1;i<=n;i++)
{
j=i;
while(j%5==0&&j!=0){
ans++;
j/=5;
}
}
printf("%d\n",ans);
}
return 0;
}
核心要點:
確定每個階乘的因數是5的多少倍,它是5的多少倍即決定了結果末尾會出現多少個零,
這兩種方法的代碼都十分簡潔明了,但第一種方法明顯對技術水平要求更高,對知識的理解要求更高,而第二種方法則將此題當成一道數學題來寫,對技術水平要求更低,對于這道題當然是首先意會哪種方法就用哪種了,都不難嘍,哈哈哈哈如果各位靚仔們考試時卡在了那個點上,課后再揣摩一下吧哈哈哈哈哈哈
關于大數的處理其實是恢常有學問的一件事啦,給自己挖個坑,以后還會更新有關大數處理相關的相關問題嘍
二.關于倒數第二道沙漏問題的規整書寫🤣🤣
(撰稿人 sunkcost ZS)
題目描述
小帥用字符輸出一個如同樣例格式的沙漏的圖形,要求如下:
用-做上下底
用\和/做斜邊
用*表示沙子
上層沙子空一行,其他行填滿;下層沙子只有中間一列,
上下底的行首無空格,所有行的行末無空格,
輸入
第一行是樣例數T(1≤T≤75), 以后的每行一個樣例,是一個整數n(6≤n≤80),n是偶數,表示沙漏的行數,
輸出
每行輸出一個對應的圖形,每個樣例之后輸出一個空行,
樣例輸入 Copy
2
6
8

針對這一道找規律題目,實際上演算法很多樣,只需要控制每一段的內容(盡管我考場上寫的顛三倒四,哈哈😂) 現在重新做一下調整供大家參考
int main()
{
int T; int a[75]; int y;
int g; int h; int j; int k;
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
scanf("%d",&a[i]);//通過陣列對每次范例的控制
}
for(int i=1;i<=T;i++)
{
y=a[i]/2; h=a[i]-5; j=0;
g=3; k=a[i]/2+1;
if((a[i]%2==0)&&(a[i]>=6)&&(a[i]<=80))//用于樣例區間控制
{
for(int x=0;x<a[i]-1;x++){
printf("-");
}
printf("\n");
printf("\\");//注意關于符號‘\’的表示
for(int x=0;x<a[i]-3;x++){
printf(" ");
}
printf("/");
printf("\n");//沙漏第一段的控制
while(g<=y)//沙漏的上半部分對沙子與沙漏的回圈
{
for(int x=0;x<g-2;x++){
printf(" ");
}
printf("\\");
for(int x=0;x<h;x++){
printf("*");
}
printf("/");
printf("\n");
g++;
h=h-2;
}
while(k>=3) //用于沙漏下半部分
{
for(int x=0;x<k-3;x++){
printf(" ");
}
printf("/");
for(int x=0;x<j;x++){
printf(" ");
}
printf("*");
for(int x=0;x<j;x++) {
printf(" ");
}
printf("\\");
printf("\n");
j=j+1;
k--;
}
for(int x=0;x<a[i]-1;x++){
printf("-");
}
printf("\n");
printf("\n"); //按照題目要求換行
}
}
return 0;
}
主要幾點就是
1 符號’‘的使用
2 每次沙漏上半部分的列印,下半部分重復回圈即可
3 注意變數的使用,例如我這里就是y代表上半部分的列長 h代 表每次’*'的次數 k控制下半部分列長
總而言之,題目不算難,就是考查回圈的使用(跟沒說一樣😒)代碼如有錯誤,望各位指正,
以上就是關于本次考試最后兩道題的決議🤣🤣
本次考試前四道題應該都是送分送的死死的,小帥切西瓜那道題考慮到2這個特殊例子就可了,小編就不在此贅述了,哈哈哈哈哈哈😘
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/234939.html
標籤:其他
