算法竞赛进阶指南学习day3

这篇博客探讨了两个编程问题:一是如何解决四柱汉诺塔问题,通过递推公式将其转换为三柱问题;二是如何利用二分和等比数列求解涉及质因数分解的数论问题。文章详细阐述了两种算法的思路,并提供了C++实现代码。此外,还介绍了维护二维前缀和解决最大子矩阵和问题的方法。
摘要由CSDN通过智能技术生成

Poj1958

概述:四柱汉诺塔

知识点:递推

思路:将四柱转化为三柱,假如有N个,那么先把i个放到2号柱上,剩下n-i个放3号柱上,再分别放到4柱上,由此可推递推式

#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int main() {
	int a[20],b[20];
	memset(b,0x3f,sizeof(b)); 
	for(int i=1;i<12;i++){
		a[i]=(1<<i)-1;
	}
	b[1]=1;
	for(int i=2;i<=12;i++){
		for(int j=1;j<i;j++) {
			b[i]=min(b[i],(b[j]<<1)+a[i-j]);	
		}
	}
	for(int i=1;i<=12;i++){
		cout<<b[i]<<" ";
	}
	return 0;
}

POJ1845 Sumdiv

知识点:二分,快幂,等比数列

思路:分解质因数,重的因数可以看成幂的形式,求这个幂的底数的0到n次幂的和,就可以转化为一个等比数列求和,但那样会超时,因此加上一点二分来求和,注意开longlong

#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
long long m;
long long y[1000];//存约数 
long long c[1000];//存约数个数 
long long quickmi(long long a,long long b){
	long long ans=1;
	while(b>0){
		if(b&1){
			ans=ans*a%9901;
		}
		a=a*a%9901;
		b>>=1;
	} 
	return ans;
}
void fen(long long n){
	m=0;
	for(int i=2;i<=sqrt(n);i++){
		if(n%i==0){
			y[++m]=i;
			c[m]=0;
		}
		while(n%i==0){//处理约数的次方的情况
			n/=i;
			c[m]++; 
		}
	}	
	if(n>1){//存储剩下的无法除尽的部分 如自己 
		y[++m]=n;
		c[m]=1;
	}
}
long long sum(long long p,long long num){
	if(num==0){
		return 1;
	}
	if(num==1){
		return p%9901+1;
	}
	if(num&1){
		return ((1+quickmi(p,(num+1)/2))*sum(p,(num-1)/2))%9901;
	}else{
		return ((1+quickmi(p,num/2))*sum(p,num/2-1)+quickmi(p,num))%9901;
	}
}

int main(){
	long long a,b;
	cin>>a>>b;
	if(a==1){
		cout<<1;
		return 0;
	}
	fen(a);
	long long ans=1;
	for(int i=1;i<=m;i++){
		ans=(ans*(sum(y[i],c[i]*b)%9901))%9901;
	}
	cout<<ans<<endl;
	return 0;
}

bzoj1218(网站打不开了)

思路:维护一个二维前缀和,然后枚举所有边长为r的正方形,更新答案

知识点:二维前缀和:自己加上加左减去左下

#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int a[5050][5050];
int main(){
	int n,r,ans=-1;
	
	cin>>n>>r; 
	for(int i=1;i<=n;i++) {
		int x,y,v;
		cin>>x>>y>>v;
		a[x+1][y+1]=v;
	}
	for(int i=1; i<5001; i++) {
		for(int j=1; j<5001; j++) {
			a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1];
		}
	}
	for(int i=1; i<5001; i++) {
		for(int j=1; j<5001; j++) {
			if(i-r>=0&&j-r>=0) {
				ans=max(ans,a[i][j]-a[i-r][j]-a[i][j-r]+a[i-r][j-r]);
			}

		}

	}
	cout<<ans;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值