填空題部分
一、在計算機存儲中,15.125GB是多少MB?
\(15.125GB * 1024 = 15488MB\)
二、1200000有多少個約數(只計算正約數)。
寫個python腳本算一下得 \(96\)
cnt=0
for i in range(1,1200001):
if not 1200000%i:
cnt=cnt+1
print(cnt)
三、一棵包含有2019個結點的樹,最多包含多少個葉結點?
昊神告訴我這叫星圖,除父節點外全部是同輩的葉子節點,答案 \(2018\)。
四、在1至2019中,有多少個數的數位中包含數字9?
注意,有的數中的數位中包含多個9,這個數只算一次。例如,1999這個數包含數字9,在計算只是算一個數。
寫個程序算一下即可,答案 \(544\)
for (int i=1;i<=2019;i++) {
int x=i,fl=0;
while (x) {
if (x%10==9) { fl=1; break; }
x/=10;
}
if (fl) sum++;
}
編程題(一)
問題描述
小明對類似於 \(hello\) 這種單詞非常感興趣,這種單詞可以正好分為四段,第一段由一個或多個輔音字母組成,第二段由一個或多個元音字母組成,第三段由一個或多個輔音字母組成,第四段由一個或多個元音字母組成。
給定一個單詞,請判斷這個單詞是否也是這種單詞,如果是請輸出yes,否則請輸出no。
元音字母包括 \(a, e, i, o, u\) ,共五個,其他均為輔音字母。
輸入格式
輸入一行,包含一個單詞,單詞中只包含小寫英文字母。
輸出格式
輸出答案,或者為 \(yes\) ,或者為 \(no\) 。
評測用例規模與約定
對於所有評測用例,單詞中的字母個數不超過 \(100\)
——————————————————————————————
模擬題意即可,四段分開判斷,遇到連續的元音/輔音就不斷讀入。
\(f\) 數組標志對應段的合法性,要注意最后還要判斷一下尾部的合法性。
代碼如下:
#include <bits/stdc++.h>
using namespace std;
char str[233];
int f[4],pos,len;
inline bool isy(char x) {
if (x=='a' || x=='e' || x=='i' || x=='o' || x=='u')
return true;
else return false;
}
int main() {
scanf("%s",str),len=strlen(str);
while (!isy(str[pos]) && pos<len) f[0]=true,pos++;
while (isy(str[pos]) && pos<len) f[1]=true,pos++;
while (!isy(str[pos]) && pos<len) f[2]=true,pos++;
while (isy(str[pos]) && pos<len) f[3]=true,pos++;
puts(f[0]&&f[1]&&f[2]&&f[3]&&len==pos?"yes":"no");
return 0;
}
編程題(二)
問題描述
在數列 \(a[1], a[2], ..., a[n]\) 中,如果對於下標 \(i, j, k\) 滿足 \(0<i<j<k<n+1\) 且 \(a[i]<a[j]<a[k]\),則稱 \(a[i], a[j], a[k]\) 為一組遞增三元組,\(a[j]\) 為遞增三元組的中心。
給定一個數列,請問數列中有多少個元素可能是遞增三元組的中心。
輸入格式
輸入的第一行包含一個整數 \(n\)。
第二行包含 \(n\) 個整數 \(a[1], a[2], ..., a[n]\) ,相鄰的整數間用空格分隔,表示給定的數列。
輸出格式
輸出一行包含一個整數,表示答案。
評測用例規模與約定
對於 \(50%\) 的評測用例,\(2 <= n <= 100\),\(0 <= Num <= 1000\) 。
對於所有評測用例,\(2 <= n <= 1000\),\(0 <= Num <= 10000\) 。
——————————————————————————————
其實就是叫我們求前面有比它小的,后面有比它大的的數的個數,想起了NOIP2014的珠心算試驗...
因為 \(n<=1000\) ,所以可以直接用 \(O(n^2)\) 暴力找。
代碼如下:
#include <bits/stdc++.h>
#define MAXN 10007
using namespace std;
int n,ans,a[MAXN];
int main() {
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++) {
bool f1=false,f2=false;
for (int j=1;j<i;j++)
if (a[j]<a[i]) { f1=true; break; }
for (int j=i+1;j<=n;i++)
if (a[j]>a[i]) { f2=true; break; }
if (f1&&f2) ans++;
}
printf("%d",ans);
return 0;
}
當然也可以用 \(ST\) 表把復雜度優化為 \(O(nlogn)\)。
代碼如下:
#include <bits/stdc++.h>
#define MAXN 10007
#define INF 0x3f3f3f3f
using namespace std;
int n,ans,t1[MAXN][20],t2[MAXN][20];
inline void init() {
for (int j=1;j<=log2(n);j++)
for (int i=1;i<=n-(1<<j)+1;i++) {
t1[i][j]=min(t1[i][j-1],t1[i+(1<<(j-1))][j-1]);
t2[i][j]=max(t2[i][j-1],t2[i+(1<<(j-1))][j-1]);
}
}
inline int q1(int l,int r) {
if (l>r) return INF;
int t=log2(r-l+1);
return min(t1[l][t],t1[r-(1<<t)+1][t]);
}
inline int q2(int l,int r) {
if (l>r) return -1;
int t=log2(r-l+1);
return max(t2[l][t],t2[r-(1<<t)+1][t]);
}
int main() {
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&t1[i][0]),t2[i][0]=t1[i][0];
init();
for (int i=1;i<=n;i++)
if (q1(1,i-1)<t1[i][0] && q2(i+1,n)>t1[i][0]) ans++;
printf("%d",ans);
}
最優是 \(O(n)\) 的,用兩個數組分別從頭和尾依次記錄一下當前最小或最大值即可,也比較簡單就不補代碼了。(感謝@11eyes 提醒)。
編程題(三)
問題描述
一個正整數如果任何一個數位不大於右邊相鄰的數位,則稱為一個數位遞增的數,例如 \(1135\) 是一個數位遞增的數,而 \(1024\) 不是一個數位遞增的數。
給定正整數 \(n\) ,請問在整數 \(1\) 至 \(n\) 中有多少個數位遞增的數?
輸入格式
輸入的第一行包含一個整數 \(n\) 。
輸出格式
輸出一行包含一個整數,表示答案。
評測用例規模與約定
對於 \(40\%\) 的評測用例,\(1 <= n <= 1000\)。
對於 \(80\%\) 的評測用例,\(1 <= n <= 100000\)。
對於所有評測用例,\(1 <= n <= 1000000\)。
——————————————————————————————
\(40\) 分的做法就是在 \((1,n)\) 里枚舉每一個數,然后判斷每位是否遞增。
但是直接構造數位遞增的數顯然是更優的,這里用遞歸進行逐位構造。
邊界條件:\(num>n\) 或 \(i=9\)
(我也不知道 \(80\) 分的范圍有啥用
代碼如下:
#include <bits/stdc++.h>
int n,ans=0;
using namespace std;
void dfs(int num) {
for (int i=num%10?num%10:1;i<=9;i++)
if (num*10+i<=n) ans++,dfs(num*10+i);
}
int main() {
scanf("%d",&n),dfs(0);
printf("%d",ans);
return 0;
}