1.找出唯二出现一次的数
唯二
思路:
如果把所有的数组全部异或起来就有一个数就是唯二的2个数字异或起来;
比如1 2 3 3 4 4;
异或到最后就得出的数字是1 2 ;
这个数字必有一个地方是1(二进制下);一个数在这个地方是1,另一个数在这个地方是0;比如k位上
这样我们就可以把这些数字分成2个集合:
一每个集合都异或起来,那么里面成对的变为0,那么剩下的就是那个数;
代码:
public static int[] findNumsAppearOnce(int[] nums) {
int sum=0;
for(int i=0;i<nums.length;++i)
{
sum^=nums[i];//将所有元素集合起来
}
int k=0;
while((sum>>k&1)==0) k++;
int x=0;
for(int i=0;i<nums.length;++i)
{
if(((nums[i]>>k)&1)==1)
{
x^=nums[i];
}
}
int y=x^sum;
int []p= {
x,y};
return p;
}
题目:
不用加减乘除计算a+b;
代码:
思路:
我们把加法拆分不进位加法和进位加法,加法满足结合律:
不进位的话用异或来进行加法:
3(11)
2(01)
异或后变为
(10)表示不进位加法:
进位的话要用到&进行计算;
&之后的位数就是进位,往左边移动一个位(向高位进位)
代码:
/*
3 4
11
10
01
异或是减法吗:
4 5
10
11
01
4 6
10
11
*/
#include <iostream>
using namespace std;
int main()
{
int num1,num2;
cin>>num1>>num2;
while(num2!=0)//如果进位还存在的话
{
int sum=num1^num2;//不进位加法先计算一下
int carry=(num1&num2)<<1//&出来的话就是需要进位加法;
num1=sum;//num1赋值为sum
num2=carry;//num2赋值为carry
}
cout<<num1;
}
t题目:
64位整数乘法;
输出ab%p;
我们可以发现 27可以看成这样
7是111
21 2的0次方 2
212的2次方 4
21*2的3次方 16
代码:
/*输入数据
如果这个位置是1的话就用这个位数代表的2进制和要乘法的数字相乘
不断到结尾,加起来总和就是
*/
#include <iostream>
using namespace std;
int main()
{
long long a,b,p,res=0;
cin>>a>>b>>p;
while(b)
{
if(b&1) res=(res+a)%p;//是一的话就加上2的该位次幂,只有是1就加上去
b>>=1;//将被乘数不断左移看看这个位置上有没有1;
a=(2*a)%p;//没移动一次位次幂就要乘以2 第一次是2,移动一次后变成了2*2=4,继续移动就是2*2*2=8;
}
cout<<res<<endl;
return 0;
}