0x00 基本算法

0x00 基本算法

0x01位运算

例题:Acwing 89. a^b

求a的b次方对p取模。
将b的二进制表示中的每一位进行计算。

#include
using namespace std;

typedef long long ll;
ll a,b,p,ans;

int main()
{
	scanf("%lld%lld%lld",&a,&b,&p);
	if(b==0) printf("%d",1%p);
	else
	{
		ans=1;
		while(b)
		{
			if(b&1)
			{
				ans=ans*a%p;
			}
			b>>=1;
			a=a*a%p;
		}
		printf("%lld",ans);
	} 
	return 0;
}
例题:Acwing 90. 64位整数乘法

求a乘b对p取模
同上

#include
using namespace std;

typedef long long ll;
ll a,b,p,k;
ll ans;

int main()
{
	scanf("%lld%lld%lld",&a,&b,&p);
	while(b)
	{
		if(b&1)
		{
			ans=(ans+a)%p;
		}
		b>>=1;
		a=(a<<1)%p;
	}
	printf("%lld",ans);
	return 0;
}
例题:Acwing 91. 最短Hamilton路径

二进制状态压缩

#include
using namespace std;

int n;
int a[50][50],f[1<<20][20];

int main()
{
	scanf("%d",&n);
	memset(f,0x3f,sizeof(f));
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			scanf("%d",&a[i][j]);
			a[j][i]=a[i][j];
		}
	}
	f[1][0]=0;
	for(int i=1;i<1<<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(i>>j&1)
			for(int k=0;k<n;k++)
			{
				if(a[j][k])
				{
					f[i][j]=min(f[i^(1<<j)][k]+a[j][k],f[i][j]);
				}
			}
		}
	}
	printf("%d",f[(1<<n)-1][n-1]);
	return 0;
}

0x02递推与递归

例题:93. 递归实现组合型枚举

注意升序排列

#include
using namespace std;

int n,m,cnt;
int ans[50],vis[50];

void dfs(int tot)
{
	if(tot==m) 
	{
		for(int i=1;i<=cnt;i++) printf("%d ",ans[i]);
		printf("\n");
		return;
	}
	for(int i=ans[cnt]==0 ? 1 : ans[cnt];i<=n;i++)
	{
		if(!vis[i])
		{
			vis[i]=1;
			ans[++cnt]=i;
			dfs(tot+1);
			vis[i]=0;
			--cnt;
		}
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	dfs(0);
	return 0;
}

0x03前缀和与差分

例题:99. 激光炸弹

二维前缀和:f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]
注意到 n 范围10000 数组开不下,但x,y范围5000,所以存储最大的x、y作数组即可。

#include
using namespace std;

int n,m,ans,r,c;
int pre[5005][5005];

int main()
{
	scanf("%d%d",&n,&m);
	int w,x,y;
	r=c=m;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&x,&y,&w);
		++x,++y; pre[x][y]=w;
		r=max(r,x); c=max(c,y);
	}
	for(int i=1;i<=r;i++)
		for(int j=1;j<=c;j++)
			pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+pre[i][j];
	for(int i=m;i<=r;i++)
	{
		for(int j=m;j<=c;j++)
		{
			ans=max(pre[i][j]-pre[i-m][j]-pre[i][j-m]+pre[i-m][j-m],ans);
		}
	}
	printf("%d",ans);
	return 0;
}

0x04二分

0x05排序

0x06倍增

0x07贪心

你可能感兴趣的:(《算法竞赛进阶指南》)