复习:位运算

发布时间 2023-12-26 21:52:28作者: miku今天吃什么

为了打篮球杯而捡起来之前学的oi

TA?那是什么东西,能吃吗?

/其实是感觉这行现状一般前景惨淡想着我还年轻趁早跑路比较好

本篇大概是位运算专题,之后以位运算为主的题目基本都会放在这里吧 主要以题目为主,大概不会出单独章节讲知识

1.求a^b%p,ab均小于1e9

直接一个个乘的话时间复杂度是O(b)

考虑位运算,任何一个自然数可以用多个2的n次方相加得到 例如10011,可以表示为\(2^0*1+ 2^1*1+2^3*0+2^4*0+2^5*1\)

如果b可以转化为一个k位的二进制数,然后a^b就可以表示为\(a*2^{k-1}*c_{k-1}*a*2^{k-2}*c_{k-2}+....*a*2^0*c_0\),其中c为0或1
每次都进行b>>1的操作,并进行b&1的判断。由于&是按位进行,所以可以判断最后一位是否是1.若是1则更新答案。并且每次循环都需要更新要乘的a值,比如如果是1011,要乘的a值则分别为a,a^2 以及a^8

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a,b,p;//求a的b次方对p取模 
ll ans=1;
int main()
{
  cin>>a>>b>>p;
  for(;b;b>>=1)
  {
  	if(b&1) ans=ans*a%p;
  	a=a*a%p;//如果末位是0则不更新ans。 
  }
  printf("%ld",ans);
  return 0;
}

2.64位整除乘法,求a*b%p

和上题思路类似,由幂变成了相乘,原本更新ans式子里的相乘变成相加,ans初值改为0即可

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a,b,p;
ll ans=0;
int main()
{
  scanf("%ld%ld%ld",&a,&b,&p);
  for(;b;b>>=1)
  {
  	if(b&1) ans=ans+a%p;
  	a=a+a%p;//如果末位是0则不更新ans。 
  }
  printf("%ld",ans);
  return 0;
}