位运算(快速幂+例题)算法竞赛进阶指南

基本概念

与运算 x&y
或运算 x|y
非运算 !x
异或 x^y
补码
1+x=0000…00
1+1111…11=0000…00
2+1111…10=0000…00
x+?=0000…00
?=~x+1(补码)
-n=~n+1(计算机中只有加法用加法来表示减法)
左移<<
7<<2 ==*2^n
111—>11100
右移>>
7>>2 ==/2^n(算数右移,第一位根据符号补充0或1)
111—>1

作用

1,用异或来实现配偶
0,1
2,3
4,5
6,7
0^1=1;
1^1=0;
4^1=5;
5^1=4
成对思想,图论,最小费用流
e[index] e[index^1] 成对
2,lowbit运算
求lowbit(1110010000)=10000
0001101111+1=0001110000
1110010000&0001110000=10000
用来求多少个一的算法复杂度与1有关
int lowbit(n)
{
return (~n+1(-n))&n;
}
位运算的算法复杂度都是O(1)的与电路运算有关

小技巧
mement(f,0x3F,sizeof f)
当为int型数据的时候 0x3f3f3f3f
当计算a+b的时候不会超过0xffffffff

快速幂


   例如:3^7
   7的二进制位111
   3^1=3      (1)
   3^2=9      (10)
   3^4=81     (100)
   3^7=3^1*3^2*3^4=3*9*81

快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高。
核心代码

int qpow(int a,int b int p)
{
    int res=1%p;t=a;
    while(b)
    {
        if(b&1)//b&1,不是将n的二进制形式000001按位做与操作,
        //只要b的最右边一位是1,为true。可以用来判断是否是偶数
        res=res*t%p;
        t=t*t%p;
        b>>=1;
    }     
}

ab%p


求 a 的 b 次方对 p 取模的值。
输入格式
三个整数 a,b,p ,在同一行用空格隔开。
输出格式
输出一个整数,表示a^b mod p的值。
数据范围
0≤a,b,p≤109 计算机一秒内能计算大概能计算107左右
数据保证 p≠0
输入样例:
3 2 7
输出样例
2

例如:37
7的二进制位111
3
1=3 (1)
32=6 (10)
3
4=12 (100)
37=31+32+34=3612

代码

#include<iostream>
using namespace std;
int main()
{
    int a,b,p;
    cin>>a>>b>>p;
    int res=1%p;
    while(b)
    {
        if(b&1)
           res=res*1ll*a%p;//这里的的乘1ll就是将res转换成long long数据类型,也可以直接定义成long long
        a=a*1ll*a%p;
        b>>=1;
    }
    cout<<res<<endl;
}

a*b%p


求 a 乘 b 对 p 取模的值。
输入格式
第一行输入整数a,第二行输入整数b,第三行输入整数p。
输出格式
输出一个整数,表示a*b mod p的值。
数据范围
1≤a,b,p≤1018
输入样例:
3
4
5
输出样例:
2
代码

#include<iostream>
using namespace std;
typedef unsigned long long ull;
int main()
{
    ull a,b,p;
    cin>>a>>b>>p;
    ull  res=0;
    while(b)
    {
        if(b&1)
           res=(res+a)%p;
        a=(a+a)%p;
        b>>=1;
    }
    cout<<res<<endl;
    return 0;
}

最短Hamilton路径


给定一张 n 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径。 Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次。
(哈密顿路径问题在上世纪七十年代初,终于被证明是“NP完全”的。据说具有这样性质的问题,难于找到一个有效的算法。实际上对于某些顶点数不到100的网络,利用现有最好的算法和计算机也需要比较荒唐的时间(比如几百年)才能确定其是否存在一条这样的路径。从图中的任意一点出发,路途中经过图中每一个结点当且仅当一次,则成为哈密顿回路。)
输入格式
第一行输入整数n。
接下来n行每行n个整数,其中第i行第j个整数表示点i到j的距离(记为a[i,j])。
对于任意的x,y,z,数据保证 a[x,x]=0,a[x,y]=a[y,x] 并且 a[x,y]+a[y,z]>=a[x,z]。
输出格式
输出一个整数,表示最短Hamilton路径的长度。
数据范围
1≤n≤20
0≤a[i,j]≤107
输入样例:
5
0 2 4 5 1
2 0 6 5 3
4 6 0 8 3
5 5 8 0 5
1 3 3 5 0
输出样例:
18

压缩dp,二进制
1,那些位置已经走过了
2,目前停止在哪个位置
f[state][n]=f[state_k][k]+weight[k][n];
注:state是二进制表达的0,代表没选,1代表选了
例如:选了0,1,3
1101–>11(十进制)
n:指当前位置
state_k是去掉j位的
k去掉j位现在的位置
weight是k位到j位的权重
(后一个,加当前选中的这个,逐渐遍历指导找到最小)

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int nn=20,mm=1<<20;
int f[mm][nn],weight[nn][nn];//c++有两个模块堆和栈,main函数里面定义的都被压在栈,const和全局变量都存在堆里面,这样做可以防止栈爆掉。
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
       for(int j=0;j<n;j++)
           cin>>weight[i][j];
    memset(f,0x3f,sizeof f);
    f[1][0]=0;
    for(int i=0;i<1<<n;i++)
       for(int j=0;j<n;j++)
          if(i>>j&1) //找到j点在的二进制位置判断
             for(int k=0;k<n;k++) //判断前一位怎么加上j位是最小
               if(i-(1<<j)>>k&1) 
                  f[i][j]=min(f[i][j],f[i-(1<<j)][k]+weight[k][j]);
    cout<<f[(1<<n)-1][n-1]<<endl;
    return 0;
}

c++有两个模块堆和栈,main函数里面定义的都被压在栈,const和全局变量都存在堆里面,这样做可以防止栈爆掉。
学习视频点击这里
2020年7月8日16:30:31

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
算法竞赛进阶指南》是一本进阶级别的书籍,不适合初学者阅读。根据引用中的描述,每一章都会总结书中的难点知识,并附上例题和习题。从引用的目录可以看出,《算法竞赛进阶指南》包含了基本算法位运算、递推与递归、前缀和与差分、二分、排序、倍增、贪心等内容,还包括了基本数据结构如栈、队列、链表、Hash、字符串、Trie、二叉堆等。此外,书中还讲解了动态规划的各种子领域,如线性dp、背包、区间dp、树形dp、状态压缩dp等。对于想要深入学习算法竞赛的读者来说,《算法竞赛进阶指南》是一本很好的参考书籍。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【算法竞赛进阶指南】学习笔记](https://blog.csdn.net/cpp_juruo/article/details/122520206)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [算法竞赛进阶指南总结(一)](https://blog.csdn.net/weixin_64393298/article/details/124234703)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值