HDU3972-求多余的两个数

来源:互联网 发布:erp生产管理系统源码 编辑:程序博客网 时间:2024/05/22 02:53

首先膜拜:

Impossible itself says 1 M possible ------ Tourist’s quote


这个题目想了两天,今晚脑子一下热,想到了第一个做法TLE,然后又找到了另外一个做法AC,回头优化第一种做法AC了。

1、对V位处理法,进行二进制分解可以求出a+b

      这样再把把V*V二进制分解,可得出a*a+b*b

      综合a+b,a*a+b*b如此可求出结果!

2、与官方给的方法相同

  Case 1:两个数相同

   我们只要把所有数字的各个数位的二进制个数保存下来,模3即可

   模剩下的数组里面非零部分必定是2,把二进制还原即可

  Case 2:两个数不同

   两个数必定有一个位上面的二进制表示不同

   开一个[i][j]31*31的数组,意思是第i位是1的所有数字第j位为1的个数

   对数组里面的所有元素模3

 

   接着,有一个很显然的想法,两个数二进制不同,那么必定有一个[i][i]是1

   把i处保存的数还原,得到一个解

   然后还有一个数是不能用同样的方法来找的,因为可能a&b==a

   也就是说,这种方法只能找到b,找不到a

   找a其实只要把[i][i]为2的二进制个数全部减去b的二进制个数,

   生下来的就是a的,还原即可


我第一次做法TLE,开了一个数组[i][j]表示i位和j位同时处于一个数中的个数!这样每次处理一个数的时间为O(35*35)显然TLE!

改进优化以后便是官方的做法了!


TLE代码:

#include<stdio.h>#include<string.h>#include<math.h>#define LL long long#define m 35int link[66][66];int d[66];int q[66];int main(){    int cas;    scanf("%d",&cas);    while (cas--)    {        int n;        memset(link,0,sizeof(link));        memset(q,0,sizeof(q));        scanf("%d",&n);        for (int i=1;i<=n;i++)        {            LL x;            scanf("%I64d",&x);            int len = 0;            while (x)            {                len++;                if (x&1)                {                    d[len]=1,q[len]=(q[len]+1)%3;                }                else                    d[len]=0;                x>>=1;            }            for (int i=1;i<=len;i++)                for (int j=1;j<=len;j++)                    if (i!=j && d[i]&&d[j])                        {                            link[i][j]=(link[i][j]+1)%3;                            link[j][i]=(link[j][i]+1)%3;                        }        }        LL a = 0,b = 0;        for (int i=1;i<=m;i++)        {            if (q[i]==2)            {                a += (1<<(i-1));                b += (1<<(i-1));                for (int j=1;j<=m;j++)                    link[i][j]=link[j][i]=0;                q[i]=0;            }        }     //   printf("%I64d %I64d\n",a,b);        int k=1;        while (k<=m && q[k]==0)            k++;        while (k<=m)        {            a += (1<<(k-1));            q[k]=0;            int t = 1;            while (t<=m && link[k][t]==0)                t++;            k = t;        }        for (k = 1;k<=m;k++)            if (q[k])                b += (1<<(k-1));        LL tmp ;        if (a>b)        {            tmp = a;            a = b;            b = tmp;        }        printf("%I64d %I64d\n",a,b);    }    return 0;}

优化后AC代码:

#include<stdio.h>#include<string.h>#include<math.h>#define LL long long#define m 37int link[66][66];int q[66];int main(){    int cas;    scanf("%d",&cas);    while (cas--)    {        int n;        memset(link,0,sizeof(link));        memset(q,0,sizeof(q));        scanf("%d",&n);        for (int i=1;i<=n;i++)        {            LL x;            scanf("%I64d",&x);            int len = 0;            int head =-1;            while (x)            {                len++;                if (x&1)                {                    q[len]=(q[len]+1)%3;                    if (head ==-1)                        head = len;                    else                        link[head][len]=(link[head][len]+1)%3;                }                x>>=1;            }        }        LL a = 0,b = 0;        for (int i=1;i<=m;i++)        {            if (q[i]==2)            {                a += (1<<(i-1));                b += (1<<(i-1));            }        }      //  printf("%I64d %I64d\n",a,b);        int k=1;        while (k<=m && q[k]==0)            k++;        if (k<=m)        {        for (int i=1;i<=m;i++)            if ((i==k&&q[i]==1) || (link[k][i]==1&&q[i]==1))            {                a += (1<<(i-1));                q[i]=0;            }        }      //  printf("%I64d %I64d\n",a,b);        for (k = 1;k<=m;k++)            if (q[k]==1)                b += (1<<(k-1));        LL tmp ;        if (a>b)        {            tmp = a;            a = b;            b = tmp;        }        printf("%I64d %I64d\n",a,b);    }    return 0;}


第一中做法代码:

#include<stdio.h>#include<string.h>#include<math.h>#define LL long long#define M 67int a[M];int b[M];LL mysqrt(LL x){    LL res = (LL)sqrt((double)x);    while (res*res<x)        res++;    while (res*res>x)        res--;    return res;}int main(){    int cas;    scanf("%d",&cas);    while (cas--)    {        int n;        memset(a,0,sizeof(a));        memset(b,0,sizeof(b));        scanf("%d",&n);        for (int i=1;i<=n;i++)        {            LL x;            scanf("%I64d",&x);            LL t = x;            int k = 0;            while (t)            {                k++;                if (t&1)                    a[k]=(a[k]+1)%3;                t>>=1;            }            t = x*x;            k = 0;            while (t)            {                k++;                if (t&1)                    b[k]=(b[k]+1)%3;                t>>=1;            }        }        LL x= 0,y = 0;        LL c= 1;        for (int i=1;i<=63;i++)        {            x+=a[i]*c;            y+=b[i]*c;            c<<=1;        }    //    printf("%I64d %I64d\n",x,y);        LL t = mysqrt(2*y-x*x);     //   printf("%I64d\n",t);        printf("%I64d %I64d\n",(x-t)/2,(x+t)/2);    }    return 0;}



原创粉丝点击