http://www.bnuoj.com/bnuoj/problem_show.php?pid=1065

下面有一个程序:
-----------------------------------------------
#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

1
2 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<iostream>
#include<stdio.h>
#include<string.h>
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;
}

BNUOJ-1065或运算的简单解法的更多相关文章

  1. c++复习一:复数运算的简单实现。

    复数运算的简单实现. 程序很简单了.基本忘光了复数,重新了解了基本概念.如何在平面表示一个复数,复数的长度|x|=开根 a^2+b^2.和四则运算. 程序基本点: 封装和抽象: 1)封装成员数据,私有 ...

  2. js中,三元运算的简单应用(?:)

    js中,三元运算的简单应用: var sinOrMul = ""; sinOrMul =(subType=="single")?("<span ...

  3. [PHP][位转换积累]之异或运算的简单加密应用

    异或的符号是^.按位异或运算, 对等长二进制模式按位或二进制数的每一位执行逻辑按位异或操作. 操作的结果是如果某位不同则该位为1, 否则该位为0. xor运算的逆运算是它本身,也就是说两次异或同一个数 ...

  4. 关于PHP位运算的简单权限设计

    写在最前面 最近想写一个简单的关于权限处理的东西,之前我也了解过用二进制数的位运算可以出色地完成这个任务.关于二进制数 的位运算,常见的就是“或.与.非”这三种简单运算了,当然,我也查看了下PHP手册 ...

  5. Java中的位运算及简单的算法应用介绍

    众所周知,计算机底层是二进制.而java作为一门计算机编程语言,也对二进制的位运算提供了完整的支持. 在java中,int是32位的,也就是说可以用来实现32位的位运算.方便起见,我们一般用16进制对 ...

  6. java位运算之简单了解

    1.十进制转化为二进制 将正整数转化为二进制的方法“除2取余,逆序排列”. 2.二进制转化为十进制 表示整数的二进制,第一位为标志位,0代表为正整数,位数从右开始,第一个位数为0,各位位数记作n,取各 ...

  7. c# 如何利用异或运算进行简单加密解密

    利用“^”异或运算对字符串进行加密 原理:按位做“异或”运算是->位值相同得1,不同得0,如下计算 1 ^ 1 = 0 1 ^ 0 = 1 0 ^ 1 = 1 0 ^ 0 = 0 例如: < ...

  8. VS Code mac版全局搜索失效最简单解法

    网上百度到的一些说法,说是添加以下命令行 "search.exclude": { "system/": true, "!/system/**/*.ps ...

  9. 使用redux简单的实现加法运算(简单的状态改变)

    描述该做啥?(action)!具体怎么做(reducer)!统一规划(store:包含reducer+所有的state) 上代码:index.ios.js import React, { Compon ...

随机推荐

  1. 【面试笔试】Java常见面试笔试总结

    Java 基础 1.有哪些数据类型 Java定义了8种简单类型:byte.short.int.long.char.float.double和boolean. 2.面向对象的语言特征 封装.继承.多态 ...

  2. Redis学习(3)-redis启动

    前端启动 tomcat,redis,mysql的端口号: mysql 3306 tomcat 8088 redis 6379 一,启动redis服务: 例如当前位置在redis安装目录下面: 启动re ...

  3. Redis学习(1)--环境配置,安装JDK,MySQL,tomcat

    Linux上安装jdk,mysql,tomcat安装 rpm命令: 相当于Windows的安装/卸载程序.可以进行程序的安装,更新,卸载,查看. 本地程序安装:rpm -ivh 程序名 本地程序查看: ...

  4. servlet 服务器HTTP响应头设置示例(response用法)

    1,Location 用于重定向,和返回状态码302结合使用. 代码示例: response.setStatus(302); response.setHeader("location&quo ...

  5. java 如何取前32位全是1的int型数据的后八位

    直接&255 因为Integer.toBinaryString(255) 是 8个1. 如果一个负数byte转成int则前面全部会补1,就是24个1和它自己的八位,,于是和八个1相&就 ...

  6. 华硕M2A-VM+AMD4000超频方法

    华硕M2A-VM+AMD4000超频方法2009-07-07 09:42 1.4000+默认外频为200,倍频已经锁定为10.5,实际运行频率为2100HZ.超频是通过提高外频来实现的,只要适当提高外 ...

  7. 腾讯云-Linux 基础入门

    Linux 基础入门 目录操作 任务时间:5min ~ 10min 创建目录 使用 mkdir 命令创建目录 mkdir $HOME/testFolder # $HOME 当前用户的家目录  root ...

  8. 微信小程序调用后台接口+热点新闻滚动展示

    1.微信JS文件,发送请求调用:  //将返回接口数据,写入Page({data})里面 //获取热点新闻,这个也是写在onload:function(){//code)里面的 wx.request( ...

  9. Python 的 Numpy 库

    Numpy: # NumPy库介绍 # NumPy的安装 #  NumPy系统是Python的一种开源的数值计算扩展 #  可用来存储和处理大型矩阵. #  因为不是Python的内嵌模块,因此 ...

  10. Extending_and_embedding_php翻译

    http://blog.csdn.net/lgg201 博客翻译了Extending_and_embedding_php