【11/9】模拟赛
第一题 集合删数
【题目描述】
一个集合有如下元素:1是集合元素;若P是集合的元素,则2 * P +1,4*P+5也是集合的元素,取出此集合中最小的K个元素,按从小到大的顺序组合成一个多位数,现要求从中删除M个数位上的数字,使得剩下的数字最大,编程输出删除前和删除后的多位数字。
注:不存在所有数被删除的情况。
【输入格式】
输入的仅一行,K,M的值,K,M均小于等于30000。
【输出格式】
输出为两行,第一行为删除前的数字,第二行为删除后的数字。
【样例输入】
5 4
【样例输出】
137915
95
【分析】
第一问,我用了一个小根堆。每次取出最小的值,删除,然后将它所产生的数加入堆中,如此反复。
第二问,看了zijingningmeng同学的题解。原文链接:http://hi.baidu.com/zijingningmeng/blog/item/4abde041ba269528cefca378.html
对于为什么会有很多9,因为我们的贪心是从前向后,删去第一个比后面数小的数字。那么最前面两个9之间的区域,如果数的个数小于还可以删除的数的个数,当然其中的数字是要全都删去的。
第二题 d-规则问题
【题目描述】
对任意给定的m(m∈N+)和n(n∈N+),满足m<n,构造一初始集合:P={x|m≤x≤n,x∈N+}(m,n≤100)。现定义一种d规则如下:若存在a∈P,且存在K∈N+ ,K>1,使得K´a∈P,则修改P为:P=P-{y|y=s´a,s∈N+ } ,并称该d规则具有分值a。现要求编制一个程序,对输入的m,n值,构造相应的初始集合P,对P每应用一次d规则就累加其相应的分值,求能得到最大累加分值的d规则序列,输出每次使用d规则时的分值和集合p的变化过程。
【输入格式】
输入仅一行,M,N的值。
【输出格式】
输出每次使用d规则时的分值和集合p的变化过程(即变化后的集合内所有的数,每个数用空格隔开),注意D后面有个空格,冒号后面有个空格。如果没有一次可以变化就输出0。
【样例输入】
样例输入1 | 样例输入2 |
1 10 | 56 57 |
【样例输出】
样例输出1 | 样例输出2 |
5 : 1 2 3 4 6 7 8 9 4 : 1 2 3 6 7 9 2 : 1 3 7 9 3 : 1 7 1 : |
0 |
【分析】
贪心做法,自己想的。
记录每个数字有几个倍数。每次从大到小找到倍数最小的那个数(还要大于0),如果两个数都最小取大数。删去他和他的倍数,同时记得把其他那些留下来了的数字的倍数更新。
考试时删数的时候没有判断数字是否存在,结果WA。
第三题 极值问题
【题目描述】
已知m、n为整数,且满足下列两个条件:
① m、n∈1,2,…,K,(1≤K≤10^9)
② (n^ 2-mn-m^2)^2=1
编一程序,对给定K,求一组满足上述两个条件的m、n,并且使m^2+n^2的值最大。例如,若K=1995,则m=987,n=1597,则m、n满足条件,且可使m^2+n^2的值最大。
【输入格式】
输入仅一行,K的值。
【输出格式】
输出仅一行,m^2+n^2的值
【样例输入】
1995
【样例输出】
3524578
【分析】
参见【11/8】模拟赛第三题。
第四题 所罗门王的藏宝图
【题目描述】
亨利男爵,约翰上校和勇敢的猎象人夸特曼又一次在绝代佳人弗拉塔的帮助下破解了所罗门王藏宝洞的按钮密码,紧闭的藏宝洞门缓缓打开.三位寻宝英雄迫不及待地冲进藏宝洞.他们完全被展现在眼前的无数奇珍异宝惊呆了.在他们还没有回过神的时候藏宝洞门又自动关闭了,藏宝洞内变得一片漆黑.藉着宝石发出的荧光他们隐约看到紧闭的洞门边有一串若隐若现的数字.面对突如其来的变故约翰上校和夸特曼的脸上露出了惊恐的神色,而亨利男爵却是气定神闲胸有成竹的样子.原来亨利男爵在开始寻宝前就熟读寻宝秘籍,早已掌握了所罗门王藏宝洞的出门密码的奥秘.根据洞门边显现的数字,用寻宝秘籍上记录的神秘方式输入与其相应的密码就可以再次打开洞门.如何获取与洞门边显现的数字对应的密码?这还得从数百年前流行的一个移棋游戏说起.
棋盘上有若干方格排成一行,每个方格中可放1枚棋子.移棋游戏的规则是任意一枚棋子可以沿水平方向跳过与其相邻的棋子进入空着的方格并吃掉被跳过的棋子.其他方式的棋子移动都不是合法移动.对于棋盘上若干棋子的初始布局,如果存在一种合法着法使得最终棋盘上只剩下1枚棋子,则称这种布局为一个完美布局.例如图4中3枚棋子的布局是一个完美布局,移动2步后棋盘上只剩下1枚棋子.用棋盘上最左端棋子开始到最右端棋子结束的方格状态表示棋盘的初始布局,可将图4中的初始布局表示为1101.其中1表示棋子,0表示空格.在棋盘上有3枚棋子的所有布局中,只有1101和1011这2种布局是完美布局,其他的布局都不是完美布局.例如对于棋盘布局111就无法通过合法移动使得棋盘上最终只剩下1枚棋子.
1101
0011
0100
如果藏宝洞门边显现的数字是n,那么与其对应的出门密码就是在棋盘上有n枚棋子时移棋游戏的完美布局数.试设计一个计算出门密码的算法,即计算移棋游戏的完美布局数.
【输入格式】
由文件Treasure.in提供输入数据,文件的第一行中有1个正整数n,表示藏宝洞门边显现的数字,即移棋游戏的棋盘初始布局中有n枚棋子,0<n<15536.
【输出格式】
将计算出的藏宝洞出门密码,即棋盘上有n枚棋子时移棋游戏的完美布局数输出到文件Treasure.out中.
【样例输入】
3
【样例输出】
2
【分析】
想了半个小时的递推式,然后放弃。
网上的题解只有这个,在30页左右。自己也没有想出来为什么。
代码
第一题
#include <stdio.h> #include <iostream> #define MAXN 30010 using namespace std; int h[MAXN * 100],a[MAXN * 100],b[MAXN]; int k,m,tot,to; void down(int x) { int p,q; p = x; q = p * 2; while (q <= tot) { if ((q + 1 <= tot) && (h[q + 1] < h[q])) ++q; if (h[p] < h[q]) return; swap(h[p],h[q]); p = q; q = p * 2; } } void del() { swap(h[1],h[tot]); --tot; down(1); } void ins(int x) { h[++tot] = x; int p,q; p = tot; q = p / 2; while (q > 0) { if (h[q] < h[p]) return; swap(h[q],h[p]); p = q; q = p / 2; } } void insa(int x) { int tot = 0; while (x) { b[++tot] = x % 10; x /= 10; } for (int i = tot;i > 0;--i) a[++to] = b[i]; } int main() { freopen("number.in","r",stdin); freopen("number.out","w",stdout); scanf("%d%d",&k,&m); h[++tot] = 1; for (int i = 1;i <= k;++i) { insa(h[1]); ins(h[1] * 2 + 1); ins(h[1] * 4 + 5); del(); } k = to; for (int i = 1;i <= k;++i) printf("%d",a[i]); printf("\n"); int tot9 = 0,wh = 0; for (int i = 1;i <= k;++i) if (a[i] == 9) if (i - tot9 - 1 <= m) { ++tot9; wh = i; } else { break; } if (wh) { for (int i = 1;i <= tot9;++i) a[i] = 9; for (int i = tot9 + 1;i - tot9 + wh <= k;++i) a[i] = a[i - tot9 + wh]; k = k - wh + tot9; m -= (wh - tot9); } for (int i = 1;i <= m;++i) { bool c = 0; for (int j = 1;j < k;++j) if (a[j] < a[j + 1]) { for (int t = j;t < k;++t) a[t] = a[t + 1]; break; } --k; } for (int i = 1;i <= k;++i) printf("%d",a[i]); return 0; }
第二题
#include <stdio.h> #define MAXN 110 int a[MAXN],num[MAXN]; int n,m,tot,x,y,min,wh; bool v[MAXN]; bool t; int main() { freopen("drule.in","r",stdin); freopen("drule.out","w",stdout); scanf("%d%d",&m,&n); for (int i = m;i <= n;++i) a[++tot] = i; for (int i = tot;i > 0;--i) { x = a[i]; for (int j = 1;j < i;++j) if (x % a[j] == 0) ++num[j]; } while (1) { min = 1000000000; wh = 0; for (int i = tot;i > 0;--i) if ((!v[i]) && (num[i]) && (num[i] < min)) { min = num[i]; wh = i; } if (!wh) break; t = 1; printf("%d : ",a[wh]); for (int i = wh;i <= tot;++i) if (!v[i]) if (a[i] % a[wh] == 0) { v[i] = 1; for (int j = 1;j < i;++j) if ((!v[j]) && (a[i] % a[j] == 0)) --num[j]; } for (int i = 1;i <= tot;++i) if (!v[i]) printf("%d ",a[i]); printf("\n"); } if (!t) printf("0\n"); return 0; }
第三题
#include <stdio.h> #define qw unsigned long long qw m,n,k,t; int main() { freopen("maxf.in","r",stdin); freopen("maxf.out","w",stdout); scanf("%I64d",&k); n = 1; while (m + n <= k) { t = n; n += m; m = t; printf("%I64d\n",m * m + n * n); } printf("%I64d\n",m * m + n * n); return 0; }
第四题
#include <stdio.h> #define MAXN 20000 int a[MAXN],b[MAXN],c[MAXN]; int n; int main() { freopen("treasure.in","r",stdin); freopen("treasure.out","w",stdout); scanf("%d",&n); a[1] = a[2] = 1; a[3] = 2; a[4] = 3; for (int i = 7;i <= n;++i) if (i & 1) c[i] = 4; b[5] = 3; for (int i = 6;i <= n;++i) b[i] = b[i - 1] + c[i]; for (int i = 5;i <= n;++i) a[i] = a[i - 1] + b[i]; printf("%d\n",a[n]); return 0; }