信息学奥赛NOIP2012普及组解题报告1.质因数分解(prime.cpp/c/pas)【问题描述】已知正整数n 是两个不同的质数的乘积,试求出较大的那个质数。
【输入】输入文件名为prime.in。
输入只有一行,包含一个正整数n。
【输出】输出文件名为prime.out。
输出只有一行,包含一个正整数p,即较大的那个质数。
【输入输出样例】【数据范围】对于60%的数据,6 ≤ n≤ 1000。
对于100%的数据,6 ≤n ≤2*109。
#include <stdio.h>#include <math.h>int main(){int n,i,k;scanf("%d",&n);for (i=2, k=sqrt(n) + 1;i<k;++i)if (n % i == 0){printf("%d\n", n / i);break;}return 0;}第二题寻宝[题目]传说很遥远的藏宝楼顶层藏着诱人的宝藏。
小明历尽千辛万苦终于找到传说中的这个藏宝楼,藏宝楼的门口竖着一个木板,上面写有几个大字:寻宝说明书。
说明书的内容如下:藏宝楼共有N+1层,最上面一层是顶层,顶层有一个房间里面藏着宝藏。
除了顶层外,藏宝楼另有N层,每层M个房间,这M个房间围成一圈并按逆时针方向依次编号为0,…,M-1。
其中一些房间有通往上一层的楼梯,每层楼的楼梯设计可能不同。
每个房间里有一个指示牌,指示牌上有一个数字x,表示从这个房间开始按逆时针方向选择第x个有楼梯的房间(假定该房间的编号为k),从该房间上楼,上楼后到达上一层的k号房间。
比如当前房间的指示牌上写着2,则按逆时针方向开始尝试,找到第2个有楼梯的房间,从该房间上楼。
如果当前房间本身就有楼梯通向上层,该房间作为第一个有楼梯的房间。
寻宝说明书的最后用红色大号字体写着:“寻宝须知:帮助你找到每层上楼房间的指示牌上的数字(即每层第一个进入的房间内指示牌上的数字)总和为打开宝箱的密钥”。
请帮助小明算出这个打开宝箱的密钥。
1 #include <stdio.h>2 int x[10003][103], fjx[103];3 bool k[10003][103];4 intmain()5 {6int n, m, s, t, key = 0, turn;7scanf("%d %d", &n, &m);8for (int i = 0, j; i < n; ++i)9for (j = 0; j < m; ++j)10scanf("%d %d", &k[i][j], &x[i][j]);11scanf("%d", &s);12 key = 0;13 for (int i = 0, j = s, h = 0, fj = 0; i < n; ++i)14 {7key = (key + x[i][s]) % 20123;8while (h < m)17 {18 if (k[i][j] == 1)19fjx[fj++] = j;20 ++h;21 ++j;22if (j == m)23j = 0;24}25t = (x[i][s] - 1) % fj;26s = fjx[t];27}28printf("%d\n", key);29return 0;30 }第三题摆花[题目]小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m 盆。
通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号。
为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到大的顺序依次摆列。
试编程计算,一共有多少种不同的摆花方案。
据说是个多重背包...但是我直接写的DP...#include <stdio.h>int a[102], f[102];int main() {int n, m, sum = 0;scanf("%d%d", &n, &m);for(int i = 1; i <= n; ++i)scanf("%d", &a[i]);f[0] = 1;for (int i = 1, j, k; i <= n; sum = 0, ++i) {for (j = m, sum = 0; j > a[i]; f[j] = sum, sum = 0, --j)for (k = j - a[i]; k <= j; sum %= 1000007, ++k)sum += f[k];for (j = a[i], sum = 0; j > -1; f[j] = sum, sum = 0, --j)for (k = 0; k <= j; sum %= 1000007, ++k)sum += f[k]; }printf("%d\n", f[m]);return 0; }第四题文化之旅[题目]有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家)。
不同的国家可能有相同的文化。
不同文化的国家对其他文化的看法不同,有些文化会排斥外来文化(即如果他学习了某种文化,则他不能到达排斥这种文化的其他国家)。
现给定各个国家间的地理关系,各个国家的文化,每种文化对其他文化的看法,以及这位使者游历的起点和终点(在起点和终点也会学习当地的文化),国家间的道路距离,试求从起点到终点最少需走多少路。
吵了很长时间的一道题, 很多人说Floyd可以直接秒杀, DFS不行. 但是有人构造出了卡死Floyd的数据, 所以保险DFS比较好. 另外要从终点开始搜, 从原点会得60(TLE). 另外CCF的数据太弱了, 不考虑文化差异能得90...总之, 这道题的数据比较弱, floyd可以过. 但是真正完全AC的是深度优先搜索.1 #include <stdio.h>2 #include <stdlib.h>3 int n, k, m, s, t, distance[101][101], culture[101], fight[101][101], search[101], p = 0;4 bool found = false;5 int min(int a, intb)6 {7return (a > b ? b : a);8}9void DFS(inttarget)10{11bool CanInqueue = true;12int queue[101] = {0}, tail = 0;13search[++p] = target;14if (target == t)15{16found = true;17return;18}19for (int i = 1, j; i <= n; ++i)20{21for (j = 1; j <= p; ++j)22{23if (search[j] == i || culture[search[j]] == culture[i] || fight[culture[i]][culture[search[j]]] == 1)24{25CanInqueue = false;26break;27}28}29if (distance[target][i] == 1001)30CanInqueue = false;31if (CanInqueue)32queue[++tail] = i;33else34CanInqueue = true;35}36 for (int i = 1; i <= tail; ++i)37 distance[s][queue[i]] = min(distance[s][queue[i]], distance[s][target] + dista nce[target][queue[i]]);38for (int i = 1; i <= tail; ++i)39DFS(queue[i]);40return;41}42intmain()43{44for (int i = 1, j; i < 101; ++i)45for (j = 1; j < 101; ++j)46distance[i][j] = 1001;47scanf("%d %d %d %d %d", &n, &k, &m, &s, &t);48for (int i = 1; i <= n; ++i)49scanf("%d", &culture[i]);50for (int i = 1, j; i <= k; ++i)51 for (j = 1; j <= k; ++j)52 scanf("%d", &fight[i][j]);53 for (int i = 0, y, z, c; i < m; ++i, distance[z][y] > c ? distance[y][z] = distance[z][ y] = c : c = 2147483646)54scanf("%d %d %d", &y, &z, &c);55DFS(s);56if (found)57printf("%d\n", distance[s][t]);58 else59 printf("-1\n");60return 0;61}NOIP2015普及组题解1. 金币 (coin.cpp/c/pas)【问题描述】国王将金币作为工资,发放给忠诚的骑士。
第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会一直这样延续下去:当连续N天每天收到N枚金币后,骑士会在之后的连续N+1天里,每天收到N+1枚金币。
请计算在前K天里,骑士一共获得了多少金币。
【输入格式】输入文件名为coin.in。
输入文件只有1行,包含一个正整数K,表示发放金币的天数。