[advanced guide to algorithm competition] basic algorithm - bit operation

a^b POJ1995 bit operation and fast power

Basics of fast exponentiation:

  • Each positive integer can be uniquely expressed as the sum of several exponentially non repeating powers of 2. (the odd number is obtained from the even number of - 1 + 1)
  • B & 1 represents the lowest bit of B (the first bit on the right); b> > = 1 can round off the lowest bit.
  • a(b+1)=ab*a;

Simple version

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define pb push_back
#define fi first
#define se second
const int N=105;
int main()
{
	ll a,b,p;scanf("%lld%lld%lld",&a,&b,&p);
	ll ans=1;
	while(b)
	{
		if(b&1) ans=ans*a%p;//If the last digit is 1, multiply by a
		b>>=1; //Shift right one bit
		a=a*a%p;//a if it changes from power 0 to power 1 
	}
	printf("%lld",ans%p);
	return 0; 
}

original edition

//#include<bits/stdc++.h>
#include<stdio.h>
typedef long long ll;
#define pb push_back
#define fi first
#define se second
const int N=105;
int main()
{
	ll t;scanf("%lld",&t);
	while(t--)
	{
		int m,h;
		scanf("%d%d",&m,&h);
		ll ans=0;
		while(h--)
		{
			ll a,b;scanf("%lld%lld",&a,&b);
			ll anst=1;
			while(b)
			{
				if(b&1) anst=anst*a%m;
				b>>=1;
				a=a*a%m;
			}
			anst%=m;
			ans+=anst;
			ans%=m;
		}
		printf("%lld\n",ans%m);
	}
	
	
	return 0; 
}

64 bit integer multiplication

Divide the multiplication into slow addition and mod, so that LL will not explode in the process (no more than 1018 in each step);
Original title

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define pb push_back
#define fi first
#define se second
const int N=105;
int main()
{
	ll a,b,p;scanf("%lld%lld%lld",&a,&b,&p);
	ll ans=0;	
	while(b)
	{
		if(b&1) ans=(ans+a)%p;	
		b>>=1;
		a*=2;
		a%=p;
	}
	printf("%lld",ans%p);
	return 0; 
}

Binary state compression: shortest Hamilton path

Original title
This is a traveling salesman problem with no polynomial solution and high algorithm complexity.
Use dp and binary compression.

About binary compression and binary representation status:
Taking n as 3 an example, we have the following situations:
3 points, each indicating whether the point passes through:

000  //Every point didn't pass
001  //Only point 0 passed
010  //Only point 1 passed
011  //....
100
101
110
111
000
001
010
011
100
101
110
111

So we found that if only point 0 and point 1 passed, we would stop at point 0 or point 1.

If we want to know the shortest path to 111, we need to know:
The shortest circuit and min of 110 (distance from 2 points to 0 points, distance from 1 point to 0 points);
The shortest circuit and min of 101 (2 – > 1 distance, 0 – > 1 distance);
The shortest circuit and min of 011 (0 - > 2,1 - > 2);
There is a little Floyd's idea that the shortest path from i to j can be the shortest from i to k + the shortest from k to j.
Combined with the above findings, we get that the shortest from i to k cannot have j, and the shortest from k to j must have J. Therefore, i to J can be from i to k + k to j without j;

In other words, if you want 111, you must get 110101001. These three are obtained by deleting one bit from 111, that is, a bit is obtained by the reverse operation.
Reverse the i-th bit of j:

i^(1<<j)  //No parentheses, but it looks better

Operation of judging that j of i does not exist but k exists: if 1 is returned, it exists

if((i^(1<<j))>>k&1)

Code of this question:

#include<bits/stdc++.h>
using namespace std;

const int N=1<<20,M=21;
int f[N][M],w[M][M];//The status of f[i][j] is I binary and reaches j 
int n;
int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			scanf("%d",&w[i][j]);
		}
	}
	
	memset(f,0x3f,sizeof(f));
	f[1][0]=0; //There is only one point and it is at this point
	
	for(int i=1;i<(1<<n);i++) //Enumerate each state
	{
		for(int j=0;j<n;j++)  //Enumerate the points of each type
		{
			if(i>>j&1) //To j, so bit J is 1 
			{
				for(int k=0;k<n;k++) //Enumerate each k case
				{
					if((i^(1<<j)>>k&1))//The j-th bit of i does not exist, but k exists
					f[i][j]=min(f[i][j],f[i^(1<<j)][k]+w[k][j]); 
				 } 
			}
		}
	 } 
	 
	printf("%d",f[(1<<n)-1][n-1]);
	return 0; 
}

You can also see y the general video explanation: video

Difficult to get up syndrome: greed + binary operation

Original title
During the test, there was an example that couldn't pass. Later, I learned that if ACwing didn't submit, some input couldn't be entered... I changed it for more than 3 hours

About this topic:

  • Characteristics of bit operation: binary representation does not carry.
  • 1e9 < 230, so it can be enumerated from bit 30 to bit 0;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<string,ll> pii;
#define pb push_back
#define fi first
#define se second
const int N=2e5+10;
int n,m;
pii a[N];
int cal_bit(int bit,int now)
{
	for(int i=0;i<n;i++)
	{
		int x=(a[i].se>>bit)&1;
		string s=a[i].fi;
		if(s=="AND") now&=x;
		else if(s=="OR") now|=x;
		else if(s=="XOR") now^=x;
	}
	return now;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++) 
	{
		string s;ll t;
		cin>>s>>t;
		a[i].fi=s,a[i].se=t;
	}
	
	ll val=0,ans=0;
	
	for(int i=30;i>=0;i--)
	{
		int res0=cal_bit(i,0);
		int res1=cal_bit(i,1);
		
		if(m>>i)
		{
			if(res0>=res1) ans|=(res0<<i);
			else ans|=(res1<<i),m-=(1<<i);
		}
		else ans|=(res0<<i);
	}
	
	printf("%d",ans);	
	return 0; 
}

Tags: Algorithm

Posted on Mon, 20 Sep 2021 23:45:17 -0400 by sublevel4