Sample test(s)
input
4
0 1 1 1
output
0
input
1
3
output
3
题目大致意思:
输入a[1],a[2]....a[n]n个非负整数,再添加最少数目的这样整数使得所有的整数以2为底的整数之后满足2^p(p>=0)的形式。
解题思路:
将输入的各个整数a[i]看看成整数的第a[i]个非零二进制位,其余为则为0,然后统计最后一个非零二进制为前面0的个数,即为最小值。例如:输入4个数分别为0,1,1,1则第0为为1,输入的1个数为3,故第1位为3%1,留下的3/2作为下位的进位。所以最终的和为111(2)不需要添加任何数。
代码:
首先对输入数据按升序排序,便于统计相同位数的个数;
分别建立列表存储不同的位,及相同该位的个数,并指向下一列
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define N 100010 4 typedef int ll; 5 ll a[N]; 6 typedef struct node 7 { 8 ll a; 9 ll mem; 10 struct node* next; 11 } Node; 12 typedef Node *List; 13 int cmp(const void *a,const void*b) 14 { 15 return *(ll *)a-*(ll *)b; 16 } 17 int main(void) 18 { 19 ll n,i,j,count=0,sum=0,carry=0; 20 List head,current,prev; 21 head=NULL; 22 scanf("%d",&n); 23 for(i=1; i<=n; i++) 24 scanf("%d",&a[i]); 25 qsort(&a[1],n,sizeof(ll),cmp);//这里值得注意,排序应当从a[1]开始, 26 for(i=1; i<=n; i++) 27 { 28 current=(List)malloc(sizeof(Node)); 29 current->next=NULL; 30 current->mem=0; 31 current->a=a[i]; 32 if(head==NULL) 33 head=current; 34 else 35 prev->next=current; 36 for(j=i; j<=n; j++) 37 { 38 if(a[j]==a[i]) 39 (current->mem)++; 40 else 41 break; 42 } 43 i=j-1;//循环变量退后一位 44 prev=current;//结构指针指向更新 45 } 46 sum+=head->a;//sum应当加上第一个非零位前面的零位, 47 while(head!=NULL) 48 { 49 count=carry+head->mem;//进位数加上当前位的重复数 50 i=head->a; 51 if(head->next==NULL)//当前为链表最后一项时终止循环 52 break; 53 else 54 { 55 while(count&&i<((head->next)->a)) 56 { 57 sum+=!(count%2); 58 count/=2; 59 i++; 60 } 61 carry=count; 62 } 63 sum+=(head->next)->a-i;//加上两个位之间的闲置0个数, 64 head=head->next; 65 } 66 while(count)//针对最后一个位进行统计,直至count为0. 67 { 68 sum+=!(count%2); 69 count/=2; 70 } 71 printf("%d\n",sum); 72 return 0; 73 }