CF_305_C. Ivan and Powers of Two

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 }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值