今年難度大了很多,也有很多毒瘤題..
這篇博客嘗試詳盡地解析NOIP2018普及初賽.
題目







答案
先附上答案

單項選擇題
1.C
送分題 其他都是輸入設備
2.D
A: $(269)_{16}=617$
B: $617$
C: $(1151)_{8}=617$
D: $(1001101011)_{2}=619$
3.D
常識性知識
$1GB=1024KB=1024*1024B$
4.A
廣域網-Wide Area Network-WAN
想Wide就可以了
5.B
CCF贊歌,最近幾乎每年都有。
直接拿今年年份減去屆數(2018-24=1984)。
6.A
小學奧數。在歷年的基礎上改了下。每8個字母($ASDFasdf$)一個循環,$81%8=1$,所以為A.
7.A
可以正經推出。但考試的時候如果不知道那可以畫幾個例子,然后帶進去算。算出來A為正確。
注意本題樹根深度記做0.
8.A
基數排序就是桶排序,所以不用比較。
沒聽說過?
B.冒泡和D.插入一定知道吧,都需要對比。C.堆排,堆的數據插入后上浮下沉操作需要比對,所以排除法選A。
9.A
看題目首先排除C和D。
然后時間復雜度一般要考慮最壞所以向上取整(然而我還是錯了)。
10.B
送分。
11.C
分類討論。
如下所示:
12.B
注意空集
13.B
小學奧數,分解質因數$10000=2^4*5^4$,2的倍數有4999個,5的倍數有1999個,除去10(2和5的公倍數)999個,加上10000這一個數,不互質的就是6000個,互質的就是10000-6000=4000個
14.B
狀壓DP常規操作,實在不行模擬也可。
15.B
不用多說,先進先出,棧。
問題求解
1
小學奧數,從③推出丁不去,又從④推出甲去了,然后由①推出沒下雨。
2
分類討論。
1-9中:1個
10-99中:1*8+10=18個
100-999中:(1+18)*8+100=252個
1000-1999中:1+18+252=271個
2000-2018中:2個
總共 1+18+252+271+2=544個
注意最后的2個要加上去,我是不會說我沒加的。
閱讀程序寫結果
1
#include <cstdio>
char st[100];
int main() {
scanf("%s", st);
for (int i = 0; st[i]; ++i) {
if ('A' <= st[i] && st[i]<= 'Z')
st[i] += 1;
}
printf("%s\n", st);
return 0;
}
讀題意就是將所有大寫字母變成字母后一位,如'A'變成'B','E'變成'F'.
輸出:RuanHuoMianTai
2
#include <cstdio>
int main()
int x;
scanf("%d",&x);
int res = 0;
for (int i=0;i<x;++i) {
if (i*i%x == 1) {
++res;
}
}
printf("%d", res);
return 0;
}
讀題意得 0-15 每一個數的平方模15 是不是等於1
枚舉和模的時候要細心
輸出:4
3
#include <iostream>
using namespace std;
int n,m;
int findans(int n,int m){
if (n==0) return m;
if (m==0) return n % 3;
return findans(n-1,m)-findans(n,m-1)+findans(n-1,m-1);
}
int main(){
cin>>n>>m;
cout<<findans(n,m)<<endl;
return 0;
}
做的時候暴力模擬,后來知道可以用表格。
$f[i][j]=f[i-1][j]-f[i][j-1]+f[i-1][j-1]$
表格長這樣
| n/mn/m | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| 1 | 1 | 0 | 3 | 2 | 5 | 4 | 7 |
| 2 | 2 | -1 | 4 | 1 | 6 | 3 | 8 |
| 3 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| 4 | 1 | 0 | 3 | 2 | 5 | 4 | 7 |
| 5 | 2 | -1 | 4 | 1 | 6 | 3 | 8 |
輸出:8
4
#include <cstdio>
int n,d[100];
bool v[100];
int main(){
scanf("%d",&n);
for (int i=0;i<n;++i) {
scanf("%d",d+i);
v[i]=false;
}
int cnt=0;
for (int i=0;i<n;++i) {
if (!v[i]){
for (int j=i;!v[j];j=d[j]) {
v[j]=true;
}
++cnt;
}
}
printf("%d\n", cnt);
return 0;
}
暴力模擬即可
輸出:6
完善程序
1.最大公約數之和
(1)
$i*i$,枚舉到$\sqrt{n}$
(2)
$n/i$
(3)
return a
(4)
a%b
(5)
gcd(a[i],a[j])+ans
2.雙向鏈表求排列
(1)
a[x]=i
(2)
i+1
(3)
R[a[i]],對稱填
(4)
a[i],剛開始對稱填錯了,雙向鏈表操作
(5)
R[i]
