博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BNUOJ-1065或运算的简单解法
阅读量:7241 次
发布时间:2019-06-29

本文共 2490 字,大约阅读时间需要 8 分钟。

下面有一个程序:
-----------------------------------------------
#include<stdio.h>
int main()
{
   int n,a[10001];
   int T;
   int i,j,k;
   int ans=0;
   scanf("%d",&T);
   while(T--)
   {
       scanf("%d",&n);
       ans=0;
       for(i=0;i<n;++i)
           scanf("%d",&a[i]);
       for(i=0;i<n;++i)
           for(j=0;j<n;++j)
               ans+=(a[i]|a[j]);
       printf("%d\n",ans);
   }
return 0;
}
-----------------------------------------------
上面这个程序的时间复杂度就是O(n^2)的,输入规模增长到原来的n倍,运行时间将会是原来的n^2倍(两重循环内部的操作的次数变为原来的n^2倍)。这样的程序对于n高达10000的数据规模运行时间显然太长了,无法达到我们的要求。所以请你帮忙修改一下这个程序(只是两重循环的部分),降低算法的时间复杂度,但是程序的功能不能改变。

Input

测试数据有多组,第一行给出了测试数据的组数T(T<100)
每组数据的第一行有一个正整数 n (1≤n≤10000)。
 
接下来同一行有n个非负整数,每个数都不超过 2^16范围。两个数之间用空格分开。
 

Output

输出有T行,每行为一个非负整数,为每组输入数据的对应输出,结果不会超出32位整数的范围。
 

Sample Input

12 18467 6334
 

Sample Output

70239

 

思路:这道题目,必须感谢队友刘庆的想法......

比如现在有n(n==3)个数,分别是:2                   5               7

将它们转化为二进制:    0010              0101         0111

那么,现在只看二进制,我们将这三个二进制加起来,但不进位,只统计二进制各个位上面的1的个数会得到:

    1    1     1    1

    0    2     2    2

这表示,二进制第三位没有1,第二位有2个1,第一位有2个1,第0位有2个1,这些位对应:2^3    2^2    2^1    2^0

那么会发现当2|2+2|5+2|7==2*2^0+n*2^1+2*2^2+0*2^3

5|2+5|5+5|7==n*2^0+2*2^1+n*2^2+0*2^3

7|2+7|5+7|7==n*2^0+n*2^1+n*2^2+0*2^3

 

发现没有,当一个数,比如7的二进制0111去或其他数的时候,若有一位本身是1,那么这一位或上与之对应的那一位(不管是0还是1)形成的新的数字的这一位都会是1;

就比如000110   与010000  或  变成010110       ,会发现只要有1的位,所形成新的二进制那一位也必然有1,那么当它与n个二进制数字或操作,所形成新的二进制数字,当原数字有1那么它对应的那一位也必然是1的.....这样,我们就只需要统计所以的二进制加起来不产生进位的情况下,每一位有多少个1就好 。

代码:

#include
#include
#include
using namespace std;struct node{ int a[20]; int cnt; int num;}s[10005];int t[20],f=0;int p[20]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072};int main(){ int text; scanf("%d",&text); while(text--) { memset(s,0,sizeof(s)); memset(t,0,sizeof(t)); int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&s[i].num); int tmp=s[i].num; while(tmp>0) { int tmp1=s[i].cnt; s[i].a[tmp1]=tmp%2; tmp/=2; s[i].cnt++; } for(int j=0;j<=15;j++) if(s[i].a[j]==1) t[j]++; //for(int i=0;i<=15;i++) //printf("%d",t[i]); } int ans=0; for(int i=1;i<=n;i++) { for(int j=0;j<=15;j++) { if(s[i].a[j]==1) { ans+=p[j]*n; } if(s[i].a[j]==0) { ans+=t[j]*p[j]; } } } printf("%d\n",ans); } return 0;}

 

转载地址:http://qfybm.baihongyu.com/

你可能感兴趣的文章
经典排序之 冒泡排序
查看>>
PHP 定义栈结构,实现min函数,获取栈最小元素,要求时间复杂度为O(1)
查看>>
ASP.NET 面试题大全
查看>>
设置 xcode 使用arc
查看>>
poj 3026 (最小生成树)
查看>>
初到深圳面试分享(上)
查看>>
Asp.net页面无刷新请求实现
查看>>
uGUI练习 开篇
查看>>
tcpdump重要笔记
查看>>
android生成apk包出现Unable to add &quot;XXX&quot; Zip add failed问题
查看>>
SSH服务器与Android通信(1)--服务器端发送数据
查看>>
C++Bulder DataSnap 内存泄露元凶
查看>>
二叉搜索树与双向链表
查看>>
Cassandra查询语言CQL的基本使用
查看>>
echo输出到stderr
查看>>
Leetcode: Search a 2D Matrix II
查看>>
Unicode与 utf8的互相转换
查看>>
Android开发周报:Flyme OS开源、经典开源项目解析
查看>>
uva 568(数学)
查看>>
【Hibernate】Hibernate系列4之配置文件详解
查看>>