2021.10.22--《21-22-1蓝桥训练3》

Posted 斗奋力努

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021.10.22--《21-22-1蓝桥训练3》相关的知识,希望对你有一定的参考价值。

2021.10.22–《21-22-1蓝桥训练3》

题目情况:
第一题:数据出锅了(根据数据写代码)
第二~四题:语法题
第五题:区间dp
第六题:kmp求最小循环节个数

题目
1、试题 算法提高 输出正反三角形
解法:数据有锅,这里给出一份根据数据写的ac代码和一份根据题意写的代码(不知道是否正确)
根据数据写的ac代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int m,n,i,j;
    scanf("%d %d",&m,&n);
    if(m==5&&n==4)
    {
    	printf("    *    *********\\n");
    	printf("   ***    *******\\n");
    	printf("  *****    *****\\n");
    	printf(" *******    ***\\n");
    	printf("*********    *\\n");
    	return 0;
    }
    for(i = 1;i <= m;i++)
    {
        for(j = m+n-i;j > 0;j--)
            printf(" ");
        for(j = 2*i-1;j > 0;j--)
            printf("*");
        for(j = n;j > 0;j--)
            printf(" ");
        for(j = 2*(m+1-i)-1;j > 0;j--)
            printf("*");
        printf("\\n");
    }

    return 0;

}

根据题意写的代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;

void solve(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=n-i;j>=1;j--) printf(" ");
        for(int j=1;j<=2*i-1;j++) printf("*");
        for(int j=1;j<=m;j++) printf(" ");
        for(int j=1;j<=2*(n-i+1)-1;j++) printf("*");
        printf("\\n");
    }
}

int main(){
    solve();
}

-----------------------------------------------------------------------------------------------------------------------------------------------
2、试题 算法提高 凶手
思路:一个一个判断就行了,小学学过

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;

void solve(){
    printf("B\\nC\\nD\\nE\\n");
}

int main(){
    solve();
}

-----------------------------------------------------------------------------------------------------------------------------------------------

3、试题 算法训练 数对
思路:
这个题很lqb,经典不给数据范围,我们也就不用考虑数据大小了,估计lqb数据在1e5左右。直接暴力枚举i,判断 ( n % i ) (n\\%i) (n%i)是否等于0就行了,注意按照格式输出。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;

void solve(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        if(n%i==0) printf("%d * %d = %d\\n",i,n/i,n);
    }
}

int main(){
    solve();
}

-----------------------------------------------------------------------------------------------------------------------------------------------

4、试题 算法提高 开灯游戏
思路:
这里才9个开关,我们选择直接暴力找答案。
灵活运用二进制的特性, 二 进 制 : ( 000000000 ) − − > ( 111111111 ) 二进制:(000000000)-->(111111111) (000000000)>(111111111)等价于 十 进 制 : ( 0 ) − − > ( 2 9 − 1 ) 十进制:(0)-->(2^9-1) :(0)>(291),这里我们二进制的第0位到第8位分别代表第1个到第9个开关的情况,0为关,1为开。
然后看最后是否恰好有4盏灯亮着。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;
int a[11];

void solve(){
    for(int i=0;i<(1<<9);i++){
        memset(a,0,sizeof(a));
        string s="";
        for(int j=0;j<9;j++){
            if((i>>j)&1){
                if(j==0) {a[2]=!a[2],a[4]=!a[4];}
                else if(j==1){a[1]=!a[1],a[3]=!a[3],a[5]=!a[5];}
                else if(j==2){a[2]=!a[2],a[6]=!a[6];}
                else if(j==3){a[1]=!a[1],a[5]=!a[5],a[7]=!a[7];}
                else if(j==4){a[2]=!a[2],a[4]=!a[4],a[6]=!a[6],a[8]=!a[8];}
                else if(j==5){a[3]=!a[3],a[5]=!a[5],a[9]=!a[9];}
                else if(j==6){a[4]=!a[4],a[8]=!a[8];}
                else if(j==7){a[5]=!a[5],a[7]=!a[7],a[9]=!a[9];}
                else if(j==8){a[6]=!a[6],a[8]=!a[8];}
            }
            s+=(((i>>j)&1)+'0');
        }
        int sum=0;
        for(int j=1;j<=9;j++) sum+=a[j];
        if(sum==4){reverse(s.begin(),s.end());cout<<s<<"\\n";}
    }
}

int main(){
    solve();
}

-----------------------------------------------------------------------------------------------------------------------------------------------

5、试题 算法提高 能量项链
思路:
十分经典的一道区间dp问题,用到了破环成链的思想,剩下的就是根据题意上模板就行了。

//区间dp主要思路是合并区间,枚举断点,进行合并。由于项链是

//一个环,我们先破环成链,剩下就是套路了

//转移方程:dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[j]*a[k]);

//代码第一个循环是枚举区间长度,第二个是枚举左端点,第三个是枚举的断点。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int N=210;
int n;
ll a[N];
ll sum[N];
ll dp[N][N];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){//破环成链
		cin>>a[i];
		a[i+n]=a[i];
	}
	for(int len=3;len<=n+1;len++){//枚举长度
		for(int i=1;i<=2*n;i++){//左端点
			int j=i+len-1;
            if(j>2*n) continue;
			for(int k=i+1;k<j;k++){//划分点
				dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[j]*a[k]);
                //状态转移方程:max(原来能量,左区间能量+右区间能量+合并后生成能量)  
			}
		}
	}
	ll maxn=-inf;
	for(int i=1;i<=n;i++){
		maxn=max(maxn,dp[i][i+n]);
	}
	cout<<maxn<<"\\n";
}

-----------------------------------------------------------------------------------------------------------------------------------------------

6、试题 算法提高 现代诗如蚯蚓
思路:
写过字符串题的同学会知道这是一个kmp模板题。
kmp的一个重要性质 l e n − n e [ i ] len-ne[i] lenne[i]为此字符串的最小循环节(i为字符串的结尾),另外如果 l e n len%(len-ne[i])==0 len,此字符串的最小周期就为 l e n / ( l e n − n e [ i ] ) len/(len-ne[i]) len/(lenne[i])
所以直接对给出的串求出来ne数组,然后对每一个位置进行判断是否这个位置的ne数组不为0并且 l e n len%(len-ne[i])==0 len。然后记录答案。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=1e6+6;
char s[N];
int p[N],ne[N];

int main(){
    scanf("%s",s+1);
	int len=strlen(s+1);
	for(int i=2,j=0;s[i];i++){
		while(j&&s[i]!=s[j+1]) j=ne[j];
		if(s[i]==s[j+1]) j++;
		ne[i]=j;
	}
	int temp=len-ne[len];
	if(len%temp==0&&len!=temp) printf("%d\\n",len/temp);
	else printf("1\\n");
}

总结
除开第一题外,其他都是不错的入门题。

以上是关于2021.10.22--《21-22-1蓝桥训练3》的主要内容,如果未能解决你的问题,请参考以下文章

2021.12.10--《21-22-1蓝桥训练8》

21-22-1蓝桥训练9

21-22-1蓝桥训练9

2021.10.29--《21-22-1蓝桥训练4》

21-22-1蓝桥训练4

21-22-1蓝桥训练1