十三届蓝桥杯 --X进制减法(数学)、统计子矩阵(二维前缀和+双指针)、积木画(DP)

题目链接:X进制减法

参考链接(参考代码是正确的)

这里对X进制的理解就是:321(对应的进制分别为8、10、2)--高位3是由2个十进制的数(即中间的数)进3次位+1个二进制位进2次位得来的,而中间的数是由低位进2次位得来的  321=3*10*2+2*2+1

/*结果WA,不知道为什么*/
#include<bits/stdc++.h>
using namespace std;
int n,ma,mb;
long long a[100005],b[100005];
const int modd=1e9+7 ;//注意下写法 

int main()
{
   cin>>n;
   cin>>ma;
   for(int i=ma;i>=1;i--) cin>>a[i];//低位在前
 cin>>mb;
   for(int i=mb;i>=1;i--) cin>>b[i];
   
    long long w[100005];//w[]存每位对应的进制 
    long long mul[100005];//mul[]存每位进制的前缀积
    //w[0]=1;
 mul[1]=1;
    for(int i=max(ma,mb);i>=1;i--){
     w[i]=max((long long)2,max(a[i],b[i])+1);
 }
 for(int i=2;i<=max(ma,mb);i++){
  mul[i]=(mul[i-1]*w[i-1])%modd;
 }
 
 long long A,B;
 for(int i=ma;i>=1;i--){
  A=(A+a[i]*mul[i])%modd;
 }
 for(int i=mb;i>=1;i--){
  B=(B+b[i]*mul[i])%modd;
 }
  cout<<(A-B+modd)%modd<<endl;//注意下写法 
}


 

题目链接:统计子矩阵

 只是使用二维前缀和过80%

/*二维前缀和*/
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long k,s[505][505],res;
int a[505][505];
int main()
{
   cin>>n>>m>>k;
   for(int i=1;i<=n;i++){
   		for(int j=1;j<=m;j++) cin>>a[i][j];
   }
   for(int i=1;i<=n;i++){
   		for(int j=1;j<=m;j++) {
   				s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+a[i][j];
		   }
   }
   for(int x1=1;x1<=n;x1++){
   		for(int x2=x1;x2<=n;x2++){
   			for(int y1=1;y1<=m;y1++){
   				for(int y2=y1;y2<=m;y2++){
   					if(x2>=x1&&y2>=y1){
   						if(s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]<=k){
   							res++;
						   }
					   }
				   }
			   }
		   }
   } 
   cout<<res;
}
/*二维前缀和+双指针*/
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long k,s[505][505],res;
int a[505][505];
int main()
{
   cin>>n>>m>>k;
   for(int i=1;i<=n;i++){
   		for(int j=1;j<=m;j++) cin>>a[i][j];
   }
   for(int i=1;i<=n;i++){
   		for(int j=1;j<=m;j++) {
   				s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+a[i][j];
		   }
   }
   res=0;
   for(int x1=1;x1<=n;x1++){
   		for(int x2=x1;x2<=n;x2++){
   			for(int y1=1,y2=y1;y2<=m;y2++){
   				while(s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]>k){
   						y1++;
				   }
				   res+=(y2-y1+1);
			   }
		   }
   } 
   cout<<res;
}

题目链接:积木画

 

 参考链接(这个参考有两个点MLE)

/*没太懂,答案输出不对*/
#include<bits/stdc++.h>
using namespace std;
const int m=1e9+7;
int n;
long long f[10000005][2];
int main()
{
   cin>>n;
   f[0][0]=1;
   for(int i=1;i<=n;i++){
   		f[i][0]=(f[i-1][1]+f[i-1][2]+f[i-1][0])%m;//在第1、2列,所以把+f[i-2][0]直接去掉即可 
   		if(i>=2){
   			f[i][0]=(f[i-2][0]+f[i][0])%m;
   			f[i][1]=(f[i-2][0]+f[i-1][2])%m;
   			f[i][2]=(f[i-2][0]+f[i-1][1])%m;
		   }
   }
   cout<<f[n][0]%m;
}另一种思路,仍然是两个点MLE

/*为什么用DP:排i列是是由前面的状态推出来的*/
#include<bits/stdc++.h>
using namespace std;
const int modd=1e9+7;
int n;
long long f[10000005][2];
//f[i][0]表示排第i列(即要给第i列排满时)第i列上没有积木,则f[i][1]表示有一个积木
int main(){
	cin>>n;
	//memset(f,0,sizeof(f));使用memset MLE,不使用有两个点MLE 
	f[1][0]=1;f[1][1]=2; //假设0列存在 
	f[2][0]=2;f[2][1]=4;
	//f[3][0]=2;f[3][1]=3;
	if(n==1) cout<<1;
	else if(n==2) cout<<2;
	else{
		for(int i=3;i<=n;i++){
			f[i][0]=(f[i-1][0]+f[i-2][0]+f[i-2][1])%modd;
			f[i][1]=(f[i-1][0]*2+f[i-1][1])%modd;
		}
		cout<<f[n][0]%modd;
	}
	
} 

砍竹子参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值