4
1 * 2 5 + 3 6 + 4
题意:
输入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; }