第十三届蓝桥杯

Posted Selvaggia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十三届蓝桥杯相关的知识,希望对你有一定的参考价值。

这里写目录标题

一、刷题统计(ceil函数返回的是等值于某最小整数的浮点值,不强制转换回int就wa,没错就连和int整数相加都wa


ceil函数我给你跪了,总之ceil(x) 返回的是 等值于 大于或等于x(一般为浮点数,可能是整数)的最小整数 的浮点数

#include <bits/stdc++.h>
using namespace std;
#define int long long int
signed main()

int res=0,sum=0;
int a,b,n;
cin>>a>>b>>n;

int x=5*a+2*b;
res+=(n/x*7);
sum+=n/x*x;
int y=n-sum;
//x=0;
//while(y>0)
//	x++;
//	if(x<=5)y-=a;
//	else y-=b;
	
//
//res+=x;
if(y>5*a)
	res=res+5+(int)ceil((y-5*a)*1.0/b);

else res+=(int)ceil(1.0*y/a);
//if(y>5*a)
//	res+=5;
//	int z=((y-5*a)%b==0)?(y-5*a)/b:(y-5*a)/b+1;
//	res+=z;
//
//else
//	int z=((y%a)==0)?y/a:y/a+1;
//	res+=z;
//
cout<<res;
  return 0;

二、修剪灌木(主要应看清楚会调转方向

#include <bits/stdc++.h>
using namespace std;
#define int long long int
int n;
const int N=10000;
int a[N];
int b[N];
signed main()
//在第一天的 早晨, 所有灌木的高度都是 0 厘米  每天从早上到傍晩会长高 1 厘米
//当修剪了最右侧的灌木后, 她会调转方向
cin>>n;
	for(int i=1;i<=n;i++)
		a[i]=2*max(n-i,i-1);
		cout<<a[i]<<endl;
	   //3 4 5
	
//	1 1 1  0 1 1
//	1 2 2  1 0 2
//	2 1 3  2 1 0
//	3 2 1  3 0 1
//	4 1 2  0 1 2
//	1 2 3  1 0 3
//	2 1 4  2 1 0
	
	
//	首先容易发现,
//	1、最高的时候永远出现在晚上未修剪之前(马上要修剪了),轮流变成0
//	2、灌木的最高长度应该是对称的(调转方向)
//	3、因为有最高高度,这应该是个循环的固定模式,即每个灌木都是从0->max 重复
//	固定模式的哪个时刻出现最高高度呢?
//	刚把a[x]砍到0后,向左(或向右)走到底a[n],再往回走到a[x]的时候
	
	
  return 0;

三、统计子矩阵(前缀和+滑动窗口⭐)

结错婚是惨过输钱,看错题惨过。。。 是不超过k不是等于k啊大佬

#include <bits/stdc++.h>
using namespace std;
#define int long long int
int n,m,k;
const int N=1005;
int a[N][N];
int b[N][N];//b[i][j],第i列 前j行的前缀和
int res=0;
void fun(int x,int y)
	int s[N];
	int sum[N];
	memset(s,sizeof(s),0);
	memset(sum,sizeof(sum),0);
	for(int i=1;i<=n;i++)
		s[i]=b[i][y]-b[i][x-1];
		sum[i]=sum[i-1]+s[i];
		
	
	//这里是暴力枚举区间,在双重循环下暴力导致超时
	//用滑动窗口(maybe)
//	for(int l=1;l<=n;l++)
//		for(int r=l;r<=n;r++)
//			if((sum[r]-sum[l-1])<=k)res++;
//		
//	
	int l=1,r=1;
	for(int r=l;r<=n;r++)
		while(sum[r]-sum[l-1]>k)
			l++;
		
		res+=r-l+1;
//此时sum[r]-sum[l-1]<=k,由于枚举的是右端点,以r为右端点,有r-l+1个空间满足条件
		
//	l l+1 l+2 l+3    (l,l+3) (l+1,l+3) (l+2,l+3) (l+3,l+3)

void fun1(int i,int ii)
//	这里a[i][j]是第j列前i行的前缀和
//我的题解b[i][j]是第i列前j行的前缀和
	int l = 1, r = 1;//滑动窗口的左右端点
   int sum = 0;//区间前缀和:[l,r]区间的累计和
   for(r = 1; r <= n; r++)//遍历右端点,根据区间和调整左端点
   
     sum += a[ii][r] - a[i-1][r];//加上右端点处的和
     while(sum > k)//区间和了,左端点右移,区间变小
     
       sum -= a[ii][l] - a[i-1][l];//减去移出去的左端点处的和
       l++;
     
     res += r - l + 1;//方法数就是找到的区间大小累加
   

signed main()
	cin>>m>>n>>k;
	for(int i=1;i<=m;i++)
		for(int j=1;j<=n;j++)
			
			cin>>a[i][j];
			b[j][i]=b[j][i-1]+a[i][j];
		
	
//	子矩阵的和
//	for(int i=1;i<=n;i++)
//		for(int j=1;j<=m;j++)	
//			cout<<b[i][j]<<" ";
//		
//		cout<<endl;
//		
	
	for(int i=1;i<=m;i++)
		for(int j=i;j<=m;j++)
			fun(i,j);
		
	
	cout<<res;
  return 0;

三个样例运行超时了

#include <bits/stdc++.h>
using namespace std;
#define int long long int
int n,m,k;
const int N=1005;
int a[N][N];
int b[N][N];//b[i][j],第i列 前j行的前缀和
int res=0;
void fun(int x,int y)
	int s[N];
	int sum[N];
	memset(s,sizeof(s),0);
	memset(sum,sizeof(sum),0);
	for(int i=1;i<=n;i++)
		s[i]=b[i][y]-b[i][x-1];
		sum[i]=sum[i-1]+s[i];
		
	
	for(int i=1;i<=n;i++)
		for(int j=i;j<=n;j++)
			if((sum[j]-sum[i-1])<=k)res++;
		
	

	

signed main()
	cin>>m>>n>>k;
	for(int i=1;i<=m;i++)
		for(int j=1;j<=n;j++)
			
			cin>>a[i][j];
			b[j][i]=b[j][i-1]+a[i][j];
		
	
//	子矩阵的和
//	for(int i=1;i<=n;i++)
//		for(int j=1;j<=m;j++)	
//			cout<<b[i][j]<<" ";
//		
//		cout<<endl;
//		
	
	for(int i=1;i<=m;i++)
		for(int j=i;j<=m;j++)
			fun(i,j);
		
	
	cout<<res;
  return 0;

四、积木画


我一直以为我是对的来着(0%通过率,excuse me?呜呜呜)
fine,我看完n=3的情况下意识地以为 组合情况 要么 长方形单独拼,L形单独拼,或者是 长方形和L形混拼(而且下意识觉得两种混拼的形式只有n=3情况中枚举的这么几种),但显然简单化了(稍微动脑想想,n=5,一个L形两个长方形,这种组合情况就超出了n=3枚举的那些情况

#include <bits/stdc++.h>
using namespace std;
#define int long long int
int n,m,k;
const int mod=1000000007;
const int N=10000005;
int dp[N];

signed main()
	cin>>n;
	dp[1]=1;
	dp[2]=2;
	dp[3]=5;
	for(int i=4;i<=n;i++)
		dp[i]=(dp[i-1]*1%mod+dp[i-2]*2%mod+dp[i-3]*5%mod)%mod;
	
	cout<<dp[n];
  return 0;

递归还是讲究一个状态转移,那么对于第 i i i 列可能会有哪几种情况呢?


(,阴影部分表示第 i − 1 i-1 i1 列已经拼好的状态,由于长方形和L形都只占两列,只需要观察第 i − 1 i-1 i1 列和第 i i i 列)
最后所求的方案数 等值于 d p [ n ] [ 4 ] dp[n][4] dp[n][4]
不用担心除了第n列之外的列上下没有被覆盖满,因为看我们的状态转移图,转移方式无一不会使得第 i − 1 i-1 i1 列存在未被覆盖的情况,由此拼图方式递推,推到第 i i i 列时,不管第 i i i 列状态咋样,第 i − 1 i-1 i1 列一定被覆盖满了
正当我以为我要AC的时候,没有一声不好意思,竟让我崩溃至此

当需要开很大的数组(这里高达 1 e 7 1e7 1e7 ),尽量不要开longlong,实在不行将中途结果用强制转化成longlong的方法防止爆int,其次就是空间本来就已经不够了,数组下标还是不要作妖从1开始,从0开始节省一点

这里给256M

一、数组太大,超内存

#define int long long int
const int N=10000005;
int dp[N][5];
vector<vector<int>> dp(n + 1, vector<int>(5));

数开八位的真敢啊你,清一色的runerror,以后超过六位数就用vector(等等, 不对,vector似乎更占空间,看这题最后的一块题解,同样不开long long,vector反而不行了,这里能过30%不过是因为是根据n的大小针对性开的,有部分测试样例n比较小

二、初始化
没错的,都是内存的错

 dp[1][4]=1;
 dp[1][0]=1;

但为什么这个能过35%
即便避开了上面两个任意让人过%0的点,也只有勉强的30%

#include <bits/stdc++.h>
using namespace std;
#define int long long int
int n,m,k;
const int mod=1000000007;
// const int N=10000005;
// int dp[N][5];

signed main()

	cin>>n;
	vector<vector<int>> dp(n + 1, vector<int>(5));
	// dp[1][4]=1;
	// dp[1][0]=1;
  dp[0][4] = 1;
	for(int i=1;i<=n;i++)
		dp[i][1]=(dp[i-1][4])%mod;
		dp[i][2]=(dp[i-1][1]+dp[i-1][3])%mod;
		dp[i][3]=(dp[i-1][1]+dp[i-1][2])%mod;
		dp[i][4]=(dp[i-1][4]+dp[i-1][3]+dp[i-1][2]+dp[i-1][1])%mod;
	
	cout<<dp[n][4];
  return 0;

AC代码 人已疯,仍然不知道在数组越界的情况下是怎么AC的,都要怀疑自己二维数组的表示一直以来是错的了

#include <bits/stdc++.h>
using namespace std;
#define LL long long int
int n,m,k;
const int mod=1000000007;
const int N=10000005;
LL dp[N][3];//改成4 变 35%,。全是超过内存限制

signed main()

    cin>>n;

//    vector<vector<LL>> dp(n + 1, vector<LL>(4));这种数组声明 30% 运行错误or超内存
//忘记LL直接0%,二维长度改成3 全军覆没0%,运行错误(数组越界
//难道两种数组声明二维长度的含义不同?
		dp[0][3] = 1;
        for (int i = 1; i <= n; i++) 
            dp[i][0] = dp[i - 1][3];
            dp[i][1] = (dp[i - 1][0] + dp[i - 1]以上是关于第十三届蓝桥杯的主要内容,如果未能解决你的问题,请参考以下文章

第十三届蓝桥杯省赛 python B组复盘(三道代码题全AC居然省一了)

第十三届蓝桥杯模拟赛(第一期)题解-代码详解(C语言)

蓝桥杯第十三届Web组国赛天气趋势A详细题解

第十三届蓝桥杯 ——刷题统计

第十三届蓝桥杯 ——刷题统计

第十三届蓝桥杯 C/C++ 大学B组 题解