砝码设计-数论

题目描述 Description

  设有一个没有刻度的天平,可以用来称量

  任务一:设计n个砝码的重量,用它们能称出尽可能多的连续整数重量。例如n=2时,设计两个砝码的重量分别为1和3,可称重为1、2、3、4的连续重量。

  任务二:给出一个重量x(一定能在上面的最优方案下的n个砝码称出),试给出称出x的方案。如在上例中,要称出x=2的方案,方法为2+1:3;称出x=4的方案,方法为:4:1+3,称出x=1的方案为1:1.注意物体放在左边。

 输入输出格式 Input/output
输入格式:
键盘输入一行,包括两个数n和x,中间用一个空格隔开。
输出格式:
屏幕输出两行,一行为n个砝码的重量(从小到大,每个数之间用一个逗号隔开),第二行为称出x的方案。
 输入输出样例 Sample input/output
样例测试点#1

输入样例:

2 2
输出样例:

1,3

2+1:3

样例测试点#2

输入样例:

2 4
输出样例:

1,3

4:1+3

 

思路:
①从这题的任务一中不难推导:当n=1时,砝码最优解为1;当n=2时,砝码最优解为1、3;当n=3时,砝码最优解为1、3、9,通过三个例子,我们大概可以得到这样一个结论:砝码的最优解与n有很紧密的相关性,砝码重量为3的0到n-1次方,接下来就用实践检验这个结论。

②由于我们的砝码只有n个,并且重量为3的0到n-1次方,所以x必然要用这些砝码表示,不与其他数字有关,并且只能用这些砝码的和或差表示,例如7=1+9-3;2=3-1。当初我最初的想法是用DFS,搜索完每一个砝码,判断是用减号还是加号,最后记录最优解,但由于这题数据范围不确定,n太大了肯定会超时,况且这和数论关系不大,所以必须要想一个简单点的方法。

③通过观察可以发现,当x除以3时,如果余数是1,意味着要在砝码盘放上1这个砝码;当x除以3时,如果余数是2,意味着要在物盘放上1这个砝码;如果除以3余数为0,就不用放1这个砝码。同理,把x除以3后四舍五入后再除以3,根据余数判断3这个砝码的位置;再把x除以3后四舍五入再除以3后更加余数判断9这个砝码的位置,以此类推…

代码如下:

 

 1 #include <stdio.h>
 2 int main()
 3 {
 4     int A[10],B[10];
 5     int n,x;//n个砝码,要称重量x 
 6     int i,j;//循环兄弟 
 7     int s;//备份用变量 
 8     bool first;
 9     scanf("%d%d",&n,&x);
10     printf("%d",A[0]=1);//无论n为何值,第一个砝码必定为1
11     /*===================================================*///解决任务一 
12     for(i=1;i<n;i++)
13     {
14         printf(",%d",A[i]=A[i-1]*3);
15         printf("\n");
16     }
17     /*===================================================*/
18     s=x;
19     for(i=0;i<n;i++)
20     {
21         if((s+A[i])%A[i+1]==0)
22         {
23             B[i]=1;
24             s=s+A[i];
25             continue;
26         }
27         if((s-A[i])%A[i+1]==0)
28         {
29             B[i]=-1;
30             s=s-A[i];
31             continue;
32         }
33         A[i]=0;
34     }
35     printf("%d",x);
36     for(i=0;i<n;i++)
37     {
38         if(B[i]>0) 
39         {
40             printf("+%d",A[i]);
41         }
42     }
43     printf(":");
44     first=true;
45     for(i=0;i<n;i++)
46     {
47         if(B[i]<0)
48         {
49             if(!first)
50             {
51                 printf("+");
52             }
53             printf("%d",A[i]);
54             first=false;
55         } 
56     }
57     printf("\n");
58     return 0;
59 }

 

posted @ 2017-01-16 10:41  Memoryヾノ战心  阅读(401)  评论(0编辑  收藏  举报