2025.2.5位运算和快速幂

快速幂和位运算

一.位运算

1.~ :取反
原:10010
~: 01101

注:相反数=该数 取反+1

有符号整数的最小负数无法求出相反数

2.|:或
a:  0010
b:  1010
a|b:1010 (有1就为1)
3.&:与
a:  1010
b:  0011
a&b:0010 (都是1才为1)

例子:判断一个数是不是2的幂

bool f(int n) {
    if (n <= 0) return false;
    return (n & (n - 1)) == 0;
}
int main() {
    int num;
    cin >> num;
    if(f(num)) {
        cout << "YES";
    } else {
        cout << "NO";
    }
    return 0;
}
4.^:异或
a:  1010
b:  0110
a^b:1100 (数一样就为0)
1.0^n=n
2.n^n=0
3.a^b^c^d=(a^c)^b^d=……
4.若a^b=c
  则a^c=b   b^c=a

例题:有a个白球,b个黑球,取出两球,若取出2白或2黑则放入 1白球,若1黑1白则放入一个黑球,求最后所剩球的颜色

联想到^同为1或0的时候得到0即白球相当于0,黑球相当于1
就相当于a个0和b个1异或
则如果b为偶则必定为白反之必定为黑
5.<< :左移 >>:右移
a:   0101010
a<<1:1010100
a>>1:0010101
6.如何打印一个数的二进制

1)数组

int a[32];
int main()
{
	//打印a的二进制
	int num=10;
	for(int i=31;i>=0;i--)
	{
		//printf("%d",a&(1<<i)==0?0:1);
		a[i]=num%2;
		num/=2;
	}
	for(int i=0;i<32;i++)
	{
		cout<<a[i];
	}
	return 0;
 } 

2)位操作打印

int y,num;
scanf("%d",&num);
for(int i=31;i>=0;i--)
{
	y=(num>>i)%2;
	printf("%d",num>0?y:-y);
}

二.快速幂

1.引入

例:求(a^b)%c. a,b,c都是整数且0<a,c<10^9, 0<b<10^18

	ll a,b,c;
	cin>>a>>b>>c;
	ll ans=1;
	for(ll i=0;i<b;i++)
	{
		ans*=a;
	}
	ans%=c;
	cout<<ans;

在计算ans*=a的时候ans可能会超出long long 的范围

算法复杂度:O(b)

2.优化

(a*b)%p=[(a%p)*(b%p)]%p

	ll a,b,c;
	cin>>a>>b>>c;
	ll ans=1;
	for(ll i=0;i<b;i++)
	{
		ans*=a;
		ans%=c;
	}
	cout<<ans;

算法复杂度:O(b) ,并未优化

3.快速幂

例:3^10 = (3^2) ^ 5 = 9 ^ 5

9^5=9 * 9^4=9 * ( 9^2 )^2=9 * 81^2

规律:指数为偶数,底数平方,指数除以2

​ 指数为奇数,乘以底数,再令指数减1

此时复杂度为:log2(10^18)

#define ll long long 
ll f(ll a,ll b,ll c)
{
	ll ans=1;
	a%=c;
	while(b)
	{
		if(b%2==1)
		{
			ans*=a;
			ans%=c; 
		}
		a=(a*a)%c;
		b/=2;
	}
	return ans;
}
int main()
{
	ll x,y,z;
	cin>>x>>y>>z;
	ll ans=f(x,y,z);
	cout<<ans;
	return 0;
 } 
4.迭代实现

例:5^13 将13用二进制表示:1101

5^13=5^(2^0)+5^(2^1)+5^(2^2)+5^(2^3)

#define ll long long 
ll f(ll a,ll b,ll c)
{
	ll ans=1;
	while(b>0)
	{
		if(b&1)
		{
			ans=(ans*a)%c;
		}
		a=(a*a)%c;
		b>>=1;   //  b/=2
	}
	return ans;
}
int main()
{
	ll x,y,z;
	cin>>x>>y>>z;
	ll ans=f(x,y,z);
	cout<<ans;
	return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值