NOIP2003普及组
第一题 乒乓球
忽略。
第二题 数字游戏
【题目描述】
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。
例如,对于下面这圈数字(n=4,m=2):
当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏。
【输入格式】
输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于104,按顺序给出圈中的数字,首尾相接。
【输出格式】
输出文件有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。
【样例输入】
4 2
4
3
-1
2
【样例输出】
7
81
【分析】
又是区间动归。
第三题 栈
【题目描述】
栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表。栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈)。
栈的重要性不言自明,任何一门数据结构的课程都会介绍栈。宁宁同学在复习栈的基本概念时,想到了一个书上没有讲过的问题,而他自己无法给出答案,所以需要你的帮忙。
宁宁考虑的是这样一个问题:一个操作数序列,从1,2,一直到n(图示为1到3的情况),栈A的深度大于n。
现在可以进行两种操作,
1、将一个数,从操作数序列的头端移到栈的头端(对应数据结构栈的push操作)
2、将一个数,从栈的头端移到输出序列的尾端(对应数据结构栈的pop操作)
使用这两种操作,由一个操作数序列就可以得到一系列的输出序列,下图所示为由1 2 3生成序列2 3 1的过程。(原始状态如上图所示)你的程序将对给定的n,计算并输出由操作数序列1,2,…,n经过操作可能得到的输出序列的总数。
【输入格式】
输入文件只含一个整数n(1≤n≤18)
【输出格式】
一个整数,即可能输出序列的总数目。
【样例输入】
3
【样例输出】
5
【分析】
递推写的。f[i][j]代表栈中有i个,没进栈的有j个。f[i][j] = f[i – 1][j + 1] + f[i + 1][j]。
答案是f[0][0]。
第四题 麦森数
【题目描述】
形如2^P-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P是个素数,2^P-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。
任务:从文件中输入P(1000<P<3100000),计算2^P-1的位数和最后500位数字(用十进制高精度数表示)
【输入格式】
文件中只包含一个整数P(1000<P<3100000)
【输出格式】
第一行:十进制高精度数2^P-1的位数。
第2-11行:十进制高精度数2^P-1的最后500位数字。(每行输出50位,共输出10行,不足500位时高位补0)
不必验证2^P-1与P是否为素数。
【样例输入】
1279
【样例输出】
386
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087
【分析】
len = (int)(n * log10(2) + 1);
另一个用高精度。
代码
第二题
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAXN 200 int s[MAXN][MAXN],g[MAXN][MAXN][10],a[MAXN],f[MAXN][MAXN][10]; int n,m,max,min; void find(int x,int y,int z) { if (f[x][y][z] != -1) return; if (z == 1) { f[x][y][z] = g[x][y][z] = s[x][y]; return; } g[x][y][z] = 10000010; for (int i = x + z - 2;i < y;++i) { find(x,i,z- 1); if (f[x][i][z - 1] * s[i + 1][y] > f[x][y][z]) f[x][y][z] = f[x][i][z - 1] * s[i + 1][y]; if (g[x][i][z - 1] * s[i + 1][y] < g[x][y][z]) g[x][y][z] = g[x][i][z - 1] * s[i + 1][y]; } } int main() { scanf("%d%d",&n,&m); for (int i = 1;i <= n;++i) { scanf("%d",&a[i]); a[i + n] = a[i]; } for (int i = 1;i <= 2 * n;++i) for (int j = i;j <= 2 * n;++j) { s[i][j] = s[i][j - 1] + a[j] + 10; s[i][j] %= 10; while (s[i][j] < 0) s[i][j] += 10; } memset(f,255,sizeof(f)); for (int i = 1;i <= n;++i) find(i,i + n - 1,m); min = 10000010; for (int i = 1;i <= n;++i) { if (f[i][i + n - 1][m] > max) max = f[i][i + n - 1][m]; if (g[i][i + n - 1][m] < min) min = g[i][i + n - 1][m]; } printf("%d\n%d\n",min,max); return 0; }
第三题
#include <stdio.h> #define MAXN 20 long long f[MAXN][MAXN]; bool v[MAXN][MAXN]; int n; long long find(int x,int y) { if ((x < 0) || (x > n) || (y < 0) || (y > n)) return 0; if (v[x][y]) return f[x][y]; f[x][y] = find(x - 1,y + 1) + find(x + 1,y); v[x][y] = 1; return f[x][y]; } int main() { scanf("%d",&n); f[0][n] = 1; v[0][n] = 1; printf("%lld\n",find(0,0)); return 0; }
第四题
#include <stdio.h> #include <string.h> #include <math.h> #define MAXN 2010 int ans[MAXN]; int n,len; void cheng(int a[]) { int c[MAXN]; memset(c,0,sizeof(c)); int x; for (int i = 1;i <= a[0];++i) { x = 0; for (int j = 1;j <= a[0];++j) { c[i + j - 1] += a[i] * a[j] + x; x = c[i + j - 1] / 10; c[i + j - 1] %= 10; } if (x) c[i + a[0]] = x; } c[0] = a[0] * 2; while ((c[0] > 1) && (!c[c[0]])) --c[0]; if (c[0] > 500) c[0] = 500; for (int i = 0;i <= 500;++i) a[i] = c[i]; } void cheng2(int a[]) { int x = 0; for (int i = 1;i <= a[0];++i) { a[i] *= 2; a[i] += x; x = a[i] / 10; a[i] %= 10; } if (x) a[++a[0]] = x; if (a[0] > 500) a[0] = 500; } void mi(int x) { if (x == 1) return; mi(x / 2); cheng(ans); if (x & 1) cheng2(ans); } int main() { scanf("%d",&n); len = (int)(n * log10(2) + 1); printf("%d\n",len); ans[1] = 2; ans[0] = 1; mi(n); int wh; for (wh = 1;wh <= ans[0];++wh) if (ans[wh] > 1) break; --ans[wh]; for (int i = wh - 1;i > 0;--i) { ans[i] += 10; --ans[i]; } for (int i = 500;i > 0;--i) { printf("%d",ans[i]); if (i % 50 == 1) printf("\n"); } return 0; }