Noip初赛整理

分辨率为 1600x900、 16 位色的位图,存储图像信息所需的空间为?
A. 2812.5KB B. 4218.75KB C. 4320KB D. 2880KB
A
1 kb = 1024 byte
16/2 = 8 byte
正数的反码是其本身
负数是除了符号位之外依次取反
正数的补码是本身
负数的补码 是 反码加1
只要考到了一般都是负数,因为正数就是一个进制转换没啥好考的。。。

存储器,运算器,控制器,输入输出设备

主机由cpu和内存ram组成
rom只读不可写入,貌似存了些底层操作
外设由外存(硬盘),输入输出设备组成
以上构成了硬件系统

总线结构 DB AB CB数据地址控制总线
地址单向,宽度决定存储器容量大小 数据双向
32bit地址总线能用2^32字节, 即4 * 2 ^ 30 = 4GB

一棵二叉树若有k层,那么节点共有2 ^ k - 1 个 ,并且其第k层节点数为2 ^(k-1)

二进制和16进制互化:
0101 1101 1111.1001
5 D F . 9

触摸屏输入输出设备都算是。。。

什么不是个人电脑的硬件组成部分? 虚拟内存(不算硬件
错排公式
\[D_n=n! \sum_{i=0}^n(-1)^i \frac{1}{i!}\]
二项式定理:

\[(a+b)^n= \sum_{k=0}^nC_n^ka^{n-k}b^k\]

常用的电子邮件协议有SMTP、POP3、IMAP4,它们都隶属于TCP/IP协议簇
WWW

选择题有:下列正确的程序段为?这种题注意“=”的含义是赋值,因为说了是程序段

初赛的代码填空可能有点水,但是选择和问题求解并不水,真的可能需要用到复杂的方法(比如DP。。。)

注意倒序存储
加法
洛谷P1601
两种写法,我更偏向于add函数里的写法

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 10000 + 10;
string a1,b1;
int a[MAXN], b[MAXN], c[MAXN];
void add(int a[], int b[], int c[], int la, int lb) {
    int len = max(la, lb), x = 0;
    for(int i=1; i<=len; i++) {
        c[i] = a[i] + b[i] + x;
        x = c[i] / 10;
        c[i] %= 10;
    }
    if(x != 0) c[++len] = x;
    for(int i=len; i; i--) {
        cout << c[i];
    }
}
int main() {
    cin >> a1 >> b1;
    if(a1[0] == '0' && b1[0] == '0') {//这种写法先判0,并且注意是字符0不是整数0,不能用!
        cout << "0";
        return 0;
    }
    int la = a1.length(), lb= b1.length();
    /*
    for(int i=0; i<la; i++) {
        a[la - i] = a1[i] - '0';
    }
    for(int i=0; i<lb; i++) {
        b[lb - i] = b1[i] - '0';
    }
    add(a, b, c, la, lb)
    */
    for(int i=0; i<la; i++) {
        a[la-i-1] = a1[i] - '0';
    }
    for(int i=0; i<lb; i++) {
        b[lb-i-1] = b1[i] - '0';
    }
    int tot = max(la, lb), x = 0;
    for(int i=0; i<tot; i++) {
        c[i] += a[i] + b[i];//这里是+=,进位都算好了
        if(c[i] >= 10) {
            c[i+1]++;
            c[i] -= 10;
        }
    }
    tot++;
    while(!c[tot]) tot--;
    for(int i=tot; i>=0; i--) {//这里是从tot开始,因为为0部位已经删去
        cout << c[i];
    }
    return 0;
} 

减法
洛谷P2142
乘法
洛谷P1303
高精除低精
洛谷P1480

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 10000 + 10;
string a1,b1;
int a[MAXN], b[MAXN], c[MAXN], d;
void add(int a[], int b[], int c[], int la, int lb) {
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    int len = max(la, lb), x = 0;
    for(int i=1; i<=len; i++) {
        c[i] = a[i] + b[i] + x;
        x = c[i] / 10;
        c[i] %= 10;
    }
    if(x != 0) c[++len] = x;
    for(int i=len; i; i--) {
        cout << c[i];
    }
}
void subt(string a1, string b1) {
    string c1;
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    bool flg = false;
    if(a1.length() < b1.length() || (a1.length() == b1.length() && a1 < b1)) {
        c1 = a1;
        a1 = b1;
        b1 = c1;
        flg = true;
    }
    if(flg) cout << "-";
    int la = a1.length(), lb = b1.length();
    for(int i=0; i<la; i++) {
        a[la-i] = a1[i] - '0';
    }
    for(int i=0; i<lb; i++) {
        b[lb-i] = b1[i] - '0';
    }
    int x = 0;
    for(int i=1; i<=la; i++) {
        c[i] = a[i] - b[i] - x;
        x = (c[i] < 0) ? 1 : 0;
        c[i] = (c[i] < 0) ? c[i] + 10 : c[i];
    }
    while(!c[la] && la > 1) la--;
    for(int i=la; i; i--) {
        cout << c[i];
    }
}

void multi(string p, string q) {
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    int lp = p.length(), lq = q.length();
    for(int i=0; i<lp; i++) {
        a[lp-i] = p[i] - '0';
    }
    for(int i=0; i<lq; i++) {
        b[lq-i] = q[i] - '0';
    }
    int len = lp + lq - 1;
    for(int i=1; i<=lp; i++) {
        for(int j=1; j<=lq; j++) {
            c[i+j-1] += a[i] * b[j];
            c[i+j] += c[i+j-1] / 10;
            c[i+j-1] %= 10;
        }
    }
    if(c[len+1] >= 1) len++;
    while(!c[len] && len > 1) len--;
    for(int i=len; i; i--) {
        cout << c[i];
    }
}

void divi(string p, int q) {
    int lp = p.length(), x = 0, s = 0, tot = 0;
    for(int i=0; i<lp; i++) {
        x = x * 10 + p[i] - '0';
        if(x / q != 0) s++;
        if(s == 0) continue;
        c[++tot] = x/ q;
        x %= q;//x就是最后的余数
    }
    for(int i=1; i<=tot; i++) {
        cout << c[i];
    }
}
int main() {
    cin >> a1 >> d;
    divi(a1, d); 
    return 0;
}

完形填空

做完题之后一定要整理思路检查一次!,因为一个陌生的题当我们模拟完之后就比较熟悉,这个时候重走一遍不仅轻车熟路,更可以找到第一次模拟疏忽的地方,避免错误

注意对称写代码,以及造个小数据带进去试试

填程序空的时候注意不要被给的代码带歪了。。。因为给的代码都很奇怪,到最后自己可能被带的也填了奇怪的东西。。。要按“目前需要做什么”来填,比如填取最优什么的,根据你自己对算法的理解,结合上下文填空。我最后一个空就因为给的代码太简单导致我以为简单到不用更新最优解。。。其实按这个算法的流程来说就应该是取最优,不能被带歪了。。。

注意边界问题,代进去看一看是否能取到边界,很多时候初始化的值和题目描述是有点不符的,特别是最后一个空,一般是某个指针-1,这个-1就是坑人的。。。而且经常有把全局变量初始化为0的情况,得仔细看看符不符合,若是一个空填上之后会越过边界,比如什么i + p 发现会超过n什么的,可能是填错了,做这种题的技巧就是尽量去填给你的代码中本来就有的,有一些是形式上具有对称性,还有一些是比较特殊的,定义了一个end2 = n,end2始终没改变过,所以填n填end2都一样,但是答案还是写了end2。。。(13年填空1)
注意填空的对称性,比如要判断两个变量哪个先写到if里面,变量名的顺序都是能从前的代码里能看出的

初赛代码经常有for不打花括号什么的奇怪操作,有时候会影响到理解(比如说一句要填的空在不在循环里面什么的)

如果说填代码的时候,显然会算的超过题目边界,即使这样没多大影响,估计也是填错了,比如15年最后一个填空题最后一个空,显然0 和 2 是需要遍历的,据此可得i-1和i+1,并不是说无所谓就不用遍历。。。

如果看到一个很奇怪的地方, 不要轻易地认为是出题人故意写出来坑人什么的,除非真的能确定,“聪明反被聪明误”
例如10年完型T1那个swap,因为传了个指针我就以为这是个无效的操作,但其实我根据swap这个名就该明白这是出题人干扰我的,如果不交换这个程序输出什么啊。。。


阅读理解

好好读题好好读题好好读题,从题干中挖掘一些信息!做题的时候一定要专注冷静认真,别再犯低级错误了!

注意阅读程序的时候很有可能坑人,比如数组下标从0开始存

先找规律,找到解决小范围问题的办法,然后多造几个数据观察一下有什么关系,最好先读一遍代码看看是做什么的,再去模拟
解决那种很难思考的递归程序要么猜那个程序是干什么的,要么暴力算

但是暴力算也有技巧,比如不要用深度优先的方式去展开搜索树,很容易乱,用广搜的方式展开搜索树有条不紊,还容易看出规律。并且记着加一些记忆化,算的次数越少越不容易错!(17年阅读T1)

总的来说就是深度优先发现规律,广度优先计算结果

例如10年阅读T4,本质是博弈,但是其实挺难看出来的,如果用广度优先的方式展开估计是算不完的,但是如果以深度优先的方式,找最特殊的,很容易就会发现r(6) = -1,r(7) = 1,然后就会发现规律
但是因为题型不定,有时深搜反而不好找规律,灵活变换才是通法

明确数组代表的含义后再做一遍

有的题注意把过程图像化,比如17年阅读程序最后一题

写递归的时候注意写下各种状态参量,比如i = 1,q = 3什么的,不要怕麻烦,也别急着返回,把第0层递归写出来
比如f(0,1,6) f(0,2,6)这样的,一目了然,不容易错

千万不要“松懈”,有疑惑的地方一定要抓住然后重新推导解决疑惑(比如一个运算满不满足交换律举个例子试试),好多次我犯了明显的错误还是因为懒得推放过了不大明确的地方,还有是求到最后一步不想干了,直接胡想答案上去(潜意识中),也没考虑其正确性,从第一步到最后一步都要认真的做,然后回头再检查一遍,看得清楚一点!

考试前要有意识地让自己进入状态


关于心态

不要一个题做不出来就郁闷,也不要一个题轻易看出解法就十分得意,这个时候往往容易掉进坑里,比如13年填空最后一题第三个和第四个,我根据我所谓的对称性,想都没想,类比上面的代码反着写了一波,然后发现不用反着写,因为他这两部分形式上是一样的。。。检查的时候还没发现这个问题(当时心态飘了),至少也得仔细看看思考一下吧。。。


错题

做题的时候一定要细心,有些答案一看就不对得好好想想。。。

二进制转十进制的时候要从0开始数

不要因为初赛的题意简单就不怎么细想直接做,事实上也要当一道题去认真思考模型,以及应该怎么去完成这件事情,用自己所学的知识认真对待!

用1,1,2,4,8,8 这几个数,组合成四位数,能有多少种组合?
难算但是数据小可以直接枚举组合
我组合是列举出来了,但是思维定势,导致我直接用A(4, 4)去计算答案
实际上每一步都要思考一下不要凭感觉就直接乘A(4,4),既然分类了,说不定计算也是分类的,乘之前要看看是不是都能乘
因为像 1 1 2 8 这样的组合全排列,会有重复,需要除以2,所以像1 1 2 8 排列一下只有12种不同的四位数
相比之下 1 2 4 8 有24种

10阅读T4
perm函数求的是字典序最小的!!!我还想了半天多个解是不是只有一个满足条件的,我以为swap换不出全排列。。。事实上感性理解函数是干什么的就好,比如这题的perm函数应该是求全排列的,证明不出来就先放着吧

(13年选择15)T(n)表示某个算法输入规模为 n 时的运算次数。如果 T(1)为常数,且有递归式 T(n) = 2*T(n / 2) + 2n,那么 T(n) = ( )
A. Θ(n)
B. Θ(n log n)
C. Θ(n2)
D. Θ(n2 log n)
B
感性理解下

(13年选择7)
斐波那契数列的定义如下:F1 = 1, F2 = 1, Fn = Fn – 1 + Fn – 2 (n ≥ 3)。如果用下面的函数计 算斐波那契数列的第 n 项,则其时间复杂度为( )。

int F(int n) 
{ 
 if (n <= 2) 
  return 1; 
 else 
  return F(n - 1) + F(n - 2); 
}

A. O(1)
B. O(n)
C. O(n2)
D. O(Fn)

其实一看就该选D,如果选ABC你想想这个题还用考吗。。。

一个求方案或者什么的题不会做就想想卡特兰数什么的,套一下试试

(12年选择16)
已知带权有向图 G 上的所有权值均为正整数,记顶点 u 到顶点 v 的最短路径的权值为 d(u, v)。若 v1, v2, v3, v4, v5 是图 G 上的顶点,且它们之间两两都存在路径可达,则以下说法正确的有( )。

A. v1到v2的最短路径可能包含一个环
B. d(v1,v2)=d(v2,v1)
C. d(v1,v3)≤d(v1,v2)+d(v2,v3)
D. 如果v1→v2→v3→v4→v5是v1到v5的一条最短路径,那么v2→v3→v4是v2到v4的一条最短路径
CD 注意是有向图

(09选择4)
在字长为16位的系统环境下,一个16位带符号整数的二进制补码为1111111111101101。其对应的十进制整数应该是:
A. 19
B. -19
C. 18
D. -18
B
二进制减1,若最后一位为1,则让最后一位减1变为0,若为0,就向前面借一位
(我看到好多个16居然把这个数按16进制展开成10进制了)

5 %10 = 5

猜你喜欢

转载自www.cnblogs.com/Zolrk/p/9785132.html