2015多校联合训练赛 hdu 5308 I Wanna Become A 24-Point Master 2015 Multi-University Training Contest 2 构造题

该博客介绍了如何使用加减乘除将给定数量的N构造为24,重点在于通过选择合适的N组合来最小化与24的差距,从而高效构造等式。对于不同数量的N,文章提供了一种策略,包括处理奇数和偶数情况的方法,确保可以构造出所需的数值。
摘要由CSDN通过智能技术生成

I Wanna Become A 24-Point Master

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 60    Accepted Submission(s): 16
Special Judge


Problem Description
Recently Rikka falls in love with an old but interesting game -- 24 points. She wants to become a master of this game, so she asks Yuta to give her some problems to practice.

Quickly, Rikka solved almost all of the problems but the remained one is really difficult:

In this problem, you need to write a program which can get 24 points with  n  numbers, which are all equal to  n .
 

Input
There are no more then 100 testcases and there are no more then 5 testcases with  n100 . Each testcase contains only one integer  n (1n105)
 

Output
For each testcase:

If there is not any way to get 24 points, print a single line with -1.

Otherwise, let  A  be an array with  2n1  numbers and at firsrt  Ai=n (1in) . You need to print  n1  lines and the  i th line contains one integer  a , one char  b  and then one integer c, where  1a,c<n+i  and  b  is "+","-","*" or "/". This line means that you let  Aa  and  Ac  do the operation  b  and store the answer into  An+i .

If your answer satisfies the following rule, we think your answer is right:

1.  A2n1=24

2. Each position of the array  A  is used at most one tine.

3. The absolute value of the numerator and denominator of each element in array  A  is no more than  109
 

Sample Input
  
  
4
 

Sample Output
  
  
1 * 2 5 + 3 6 + 4
 

Source


题意:

输入N。用N个N通过加减乘除得到24.中间过程得到的数字可以用分数表示,不能截断小数。

分析:前几个数字打表吧。很容易写的。但是我队员(GMY)也是写的很辛苦啊。========(现在看到是修改过后的,所以打表的部分少了)


后面的数字这样处理:

选a个N相加  使得|a*N-24|最小,这样做的目的是为了减少用于构造24的N的使用量。

且令b = |24-a*N|  (a*N+b = 24 或者a*N-b = 24)构造这个等式就可以了。 

那么用b+1个N就能构造 b了 。方法:   (N *b)/N =  b

剩下left = N - a - b - 1个N。用left个N构造0即可。

显然left >= 2 (7特判了,就不怕有bug了)

如果left 为奇数

       构造  (N*(left/2) - N(left/2))/N = 0

 否则  构造  N*(left/2) - N(left/2) = 0 

所以left个N一定可以构造出0的


最后看b > 0 那么用a*N - b

否则用a*N + b

当然要特别考虑b = 0,的情况。


因为保证left > 0 了。所以先构造出0.方便后面的运算。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;


int main(){
    int n;
    while(~scanf("%d",&n))
    {
        if( n == 1 || n == 2 || n == 3  ){
            printf("-1\n");
        }
        else if( n == 4 )
            printf("1 * 2\n5 + 3\n6 + 4\n");
        else if( n == 5 )
            printf("1 * 2\n6 * 3\n7 - 4\n8 / 5\n");
        else if( n == 7 )
            printf("1 + 2\n8 + 3\n4 + 5\n10 + 6\n11 / 7\n9 + 12\n"); //为了保证left > 1 n = 7 特判
        else {
            int i,j,k,q,p,left,need;
            for(i = 0;;i++){
                if(abs(i*n - 24) <= abs(i*n+n-24) )
                    break;
            }
            int a = i;    //算出几个N相加会最接近于24
            int fx = 24 - a*n;  //算出  24 -  a * N 关于0的大小
            if( abs(24-a*n) > 0 )need = abs(24-a*n) + 1;
            else need = 0;     //算出需要need个N来构造  出|24 - a*N|
            left = n - need - i; //用left个N构造出0

            //用left个N构造0
            printf("1 - 2\n");
            p = n + 1;
            i = 3;
            j = 0;
            for(;i <= (left - left% 2); ){
                if(j & 1 ){
                    printf("%d - %d\n",p++,i++);
                }
                else printf("%d + %d\n",p++,i++);
                j ^= 1;
            }
            //left 为奇数,多计算一次 0 / N
            if(left % 2 == 1){
                printf("%d / %d\n",p++,i++);
            }

            //构造a个N相加的和
            q = i;
            for(i = 0;i < a; i++){
                printf("%d + %d\n",p++,q++);
            }

            int xp;
            if(need > 0){
                //need = 2 直接做除法,否则先做加法,最后做除法
                if(need != 2){
                    printf("%d + %d\n",q,q+1);
                    q += 2;
                    xp = p + 1;
                    for(; q < n; ){
                        printf("%d + %d\n",xp++,q++);
                    }
                    printf("%d / %d\n",xp++,q++);
                }
                else {
                    printf("%d / %d\n",q,q+i);
                    xp = p + 1;

                }
                //判断是加法还是减法
                if(fx > 0)
                    printf("%d + %d\n",p,xp);
                else
                    printf("%d - %d\n",p,xp);
            }
        }
    }
    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值