Java代码题m个小朋友分糖果,王道论坛研究生机试练习赛(二)

昨天在微博上看到王道论坛说晚上有机试练习赛(http://ac.jobdu.com/contest.php?cid=1053),想来反正也没什么事,何不参加一下。于是晚上吃完饭回到实验室,等着七点开始做题。练习赛结束了,虽然自己全部AC,但感觉时间花的有点长,主要卡在第三道求公约数个数上。看来自己的数论真的弱爆了。现将自己对这四道解题的看法归纳一下,总的来说题目不算很难,前两道超级水,第三道考素数筛选以及因式分解,第四道动态规划。

一、调整方阵

对应题目1470:http://ac.jobdu.com/problem.php?pid=1470

题目描述:

输入一个N(N<=10)阶方阵,按照如下方式调整方阵:

1.将第一列中最大数所在的行与第一行对调。

2.将第二列中从第二行到第N行最大数所在的行与第二行对调。

依此类推...

N-1.将第N-1列中从第N-1行到第N行最大数所在的行与第N-1行对调。

N.输出这个方阵

输入:

包含多组测试数据,每组测试数据第一行为一个整数N,表示方阵的阶数.

接下来输入这个N阶方阵.

输出:

调整后的方阵

样例输入:

4

3 6 8 7

6 7 5 3

8 6 5 3

9 8 7 2

样例输出:

9 8 7 2

6 7 5 3

3 6 8 7

8 6 5 3

水题,就不多说了。代码

69c5a8ac3fa60e0848d784a6dd461da6.png1 #include

2

3 int data[10][10];4

5 void adjustment(int i,intn);6 intmain()7 {8 intN;9 inti,j;10 while(scanf("%d",&N) !=EOF){11 for(i=0;i

27 void adjustment(int i,intn)28 {29 int max_i =i;30 int j = i+1;31 int temp[10];32 for(;jdata[max_i][i])34 max_i =j;35 if(max_i !=i){36 for(j=0;j

69c5a8ac3fa60e0848d784a6dd461da6.png

二、货币问题

对应题目1549:http://ac.jobdu.com/problem.php?pid=1549

题目描述:

已知有面值为1元,2元,5元,10元,20元,50元,100元的货币若干(可认为无穷多),需支付价格为x的物品,并需要恰好支付,即没有找零产生。

求,至少需要几张货币才能完成支付。

如,若支付价格为12元的物品,最少需要一张10元和一张2元,即两张货币就可完成支付。

输入:

输入包含多组测试数据,每组仅包含一个整数p(1<=p<=100000000),为需支付的物品价格。

输出:

对于每组输入数据,输出仅一个整数,代表最少需要的货币张数。

样例输入:

10

11

13

样例输出:

1

2

3

也是水题吧,有点贪心的思想吧。先尽可能用最大面值,然后依次考虑较小面值。这题如果限制货币的数量的话,应该就是0-1背包问题吧。

代码

69c5a8ac3fa60e0848d784a6dd461da6.png1 #include

2

3 intmain()4 {5 intp;6 inti;7 intsum;8 int money[7] = {1,2,5,10,20,50,100};9 while(scanf("%d",&p) !=EOF){10 sum = 0;11 for(i=6;i>=0;--i){12 sum += (p/money[i]);13 p %=money[i];14 }15 printf("%d\n",sum);16 }17 return 0;18 }

69c5a8ac3fa60e0848d784a6dd461da6.png

三、公约数

对应题目1493:http://ac.jobdu.com/problem.php?pid=1493

题目描述:

给定两个正整数a,b(1<=a,b<=100000000),计算他们公约数的个数。

如给定正整数8和16,他们的公约数有:1、2、4、8,所以输出为4。

输入:

输入包含多组测试数据,每组测试数据一行,包含两个整数a,b。

输出:

对于每组测试数据,输出为一个整数,表示a和b的公约数个数。

样例输入:

8 16

22 16

样例输出:

4

2

一直被卡在这道题的超时上。我的做法:采用素数筛选法通过函数computePrime(int n,int

maxC)返回第n个素数,其中只需要判断maxC之前的数,注意为了减少空间,我把所有的偶数(当然除了2)都去掉了,所以flag数组只有总数M的一半。在主函数里,首先求出最大公约数,则公约数的个数就等于这个最大公约数的所有约数个数,然后对这个公约数进行因式分解。即假设最大公约数为maxC,则其因式分解为:

\begin{equation*}maxC=p_1^{x_1}\times p_2^{x_2}\times\cdots\times

p_m^{x_m}\end{equation*}

所以其公约数个数为: $(x_1+1)\times(x_2+1)\times\cdots\times(x_m+1)$,这个好像叫约数个数定理吧。

代码:

69c5a8ac3fa60e0848d784a6dd461da6.png1 #include

2 #include

3

4 #define M 100000000

5 bool flag[M/2];6 int prime[6000000];7 intprimeNum;8

9 int computePrime(int n,intmaxC)10 {11 if(n == 1){12 prime[primeNum++] = 2;13 return 2;14 }15 if(n == 2){16 prime[primeNum++] = 3;17 return 3;18 }19 inti,j;20 intpos;21 i = prime[primeNum-1]+2;22 while(primeNum >1);24 if(!flag[pos]){25 prime[primeNum++] =i;26 j = 3*i;27 while(j<=maxC){28 flag[(j-3)>>1] = 1;29 j += (i<<1);30 }31 }32 i += 2;33 }34 return prime[n-1];35 }36 intmain()37 {38 inta,b;39 intsum;40 intmaxC,i,j;41 primeNum = 0;42 while(scanf("%d%d",&a,&b) !=EOF){43 intt;44 while(a%b != 0){45 t =a;46 a =b;47 b = t%b;48 }49 maxC =b;50 sum = 1;51 i = 0;52 intprime_i;53 while(maxC != 1){54 prime_i = computePrime(i+1,maxC);55 if(maxC %prime_i)56 ++i;57 else{58 t=0;59 while(maxC%prime_i == 0){60 ++t;61 maxC /=prime_i;62 }63 sum *= (t+1);64 ++i;65 }66 }67 printf("%d\n",sum);68 }69 return 0;70 }

69c5a8ac3fa60e0848d784a6dd461da6.png

四、分糖果

对应题目1550:http://ac.jobdu.com/problem.php?pid=1550

题目描述:

给从左至右排好队的小朋友们分糖果,

要求:

1.每个小朋友都有一个得分,任意两个相邻的小朋友,得分较高的所得的糖果必须大于得分较低的,相等则不作要求。

2.每个小朋友至少获得一个糖果。

求,至少需要的糖果数。

输入:

输入包含多组测试数据,每组测试数据由一个整数n(1<=n<=100000)开头,接下去一行包含n个整数,代表每个小朋友的分数Si(1<=Si<=10000)。

输出:

对于每组测试数据,输出一个整数,代表至少需要的糖果数。

样例输入:

3

1 10 1

3

6 2 3

2

1 1

样例输出:

4

5

2

看完题目,第一反应是要用动态规划解决。其最优子结构为:假如我们已经解决了(s,mid)以及(mid+1,e)这两个子问题,那么我们现在要按如下方法解决子问题(s,e)。首先分三种情况:1)score[mid]=score[mid+1];2)score[mid]

> score[mid+1];3)score[mid] < score[mid+1]。

1)由于分数相等的话对糖果的分配不做要求,所以最小的糖果数是两个子问题的和。

2)左边的分数大。此时若左边的糖果多的话,则最小糖果数也是两个子问题的和;否则调整左边的糖果分配,先将[mid]位置的糖果数分配为比[mid+1]位置多一个,然后从mid到s进行调整。

3)右边的分数大。此时若右边的糖果多的话,则最小糖果数也是两个子问题的和;否则调整右边的糖果分配,先将[mid+1]位置的糖果数分配为比[mid]位置多一个,然后从mid+1到e进行调整。

代码

69c5a8ac3fa60e0848d784a6dd461da6.png1 #include

2

3 int candyNum[100000];4 int score[100000];5

6 int distributeCandy(int,int);7 intmain()8 {9 intn,i;10 while(scanf("%d",&n)!=EOF){11 for(i=0;i

19 int distributeCandy(int s,inte)20 {21 if(s ==e){22 candyNum[s] = 1;23 return 1;24 }else if(s+1 ==e){25 if(score[s] ==score[e]){26 candyNum[s] = candyNum[e] = 1;27 return 2;28 }else if(score[s] >score[e]){29 candyNum[s] = 2;30 candyNum[e] = 1;31 return 3;32 }else{33 candyNum[s] = 1;34 candyNum[e] = 2;35 return 3;36 }37 }else{38 int total = 0;39 int mid = (s+e)/2;40 int left =distributeCandy(s,mid);41 int right = distributeCandy(mid+1,e);42 if(score[mid] == score[mid+1]){43 return left +right;44 }else if(score[mid] > score[mid+1]){45 if(candyNum[mid] > candyNum[mid+1])46 return left+right;47 else{48 total += (candyNum[mid+1]+1-candyNum[mid]);49 candyNum[mid] = candyNum[mid+1] + 1;50 int i = mid - 1;51 int totalAdd = 0;52 for(;i>=s;--i){53 if(score[i] <= score[i+1] || (score[i] > score[i+1] && candyNum[i] > candyNum[i+1]))54 break;55 else{56 total += (candyNum[i+1]+1-candyNum[i]);57 candyNum[i] = candyNum[i+1] +1;58 }59 }60 return left+right+total;61 }62 }else{63 if(candyNum[mid] < candyNum[mid+1])64 return left+right;65 else{66 total += (candyNum[mid]+1-candyNum[mid+1]);67 candyNum[mid+1] = candyNum[mid]+1;68 int i = mid+2;69 for(;i<=e;++i){70 if(score[i] <= score[i-1] || (score[i] > score[i-1] && candyNum[i] > candyNum[i-1]))71 break;72 else{73 total += (candyNum[i-1]+1-candyNum[i]);74 candyNum[i] = candyNum[i-1]+1;75 }76 }77 return left+right+total;78 }79 }80 }81 }

69c5a8ac3fa60e0848d784a6dd461da6.png

PS:此次第一名竟然在十四分钟内四道题全部AC,真是不可思议,估计有些题之前做过,直接拷贝过去或者稍微改一下。

原文:http://www.cnblogs.com/boostable/p/online_judge_1470_1549_1493_1550.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值