蓝桥杯 第 1 场 小白入门赛

目录

1.蘑菇炸弹

2.构造数字

3.小蓝的金牌梦

4.合并石子加强版

5.简单的LIS问题

6.期望次数


1.蘑菇炸弹

我们直接依照题目 在中间位置的数进行模拟即可

void solve(){
   
    cin>>n;
    vector<int> a(n+1);
    for(int i=1;i<=n;i++) cin>>a[i];
    
    int ans=0;
    for(int i=2;i<n;i++){
        if(a[i]>=a[i-1]+a[i+1]) ans++;
    }
    
    cout<<ans<<endl;
    return ;
}

2.构造数字

我们需要构造的数字最大,由于数位已经告诉我们,所以明显的有一个贪心的策略:从最高位置开始从最大的数开始遍历是否可以填可以填减去看下一位即可

void solve(){
   
    cin>>n>>m;
    
    for(int i=1;i<=n;i++){
    	for(int j=9;j>=0;j--){
    		if(m>=j){
    			cout<<j;
    			m-=j;
    			break;
    		}
    	}	
    }
    return ;
}

3.小蓝的金牌梦

我们有一个错误的想法就是找出最大的质数x然后直接求长度x的即可,为什么是错误的呢?因为题目中的元素带有负数,所以我们要求出所有满足的来比较最大值,我们可以考虑使用线性筛来求出所有的质数然后前缀和来求解即可

vector<int> primes;
int cnt;

void solve(){
   
    cin>>n;
    
    vector<LL> a(n+5);
    for(int i=1;i<=n;i++) cin>>a[i],a[i]+=a[i-1];
    
    auto get = [&](){
    	vector<bool> st(n+5);
    	for(int i=2;i<=n;i++){
    		if(!st[i]){
    			primes.push_back(i);
    			cnt++;
    		}
    		for(int j=0;primes[j]<=n/i;j++){
    			st[i*primes[j]]=true;
    			if(i%primes[j]==0) break;
    		}
    	}
    };
    
    get();
    LL ans=-1e18;// 注意初始化防止过小
   	for(int i=1;i<=n;i++){
   		for(auto&v:primes){
   			if(i<v) break;
   			ans=max(ans,a[i]-a[i-v]);
   		}
   	}
   	
   	cout<<ans<<endl;
    return ;
}

4.合并石子加强版

首先我们不要直接先入为主认为是区间dp,区间dp的时间复杂度一般是n^3也不现实,我们接着找是不是具有什么性质找最简模型

a  b  c  -> 

1: 先左后右  a*b+(a+b)*c = a*b+a*c+b*c

2: 先右后左  b*c+(b+c)*a = a*b+a*c+b*c

我们可以发现无论左右结果不会变的那么也就是我们这个结果是不受操作所影响的,所以我们选择最优的操作直接从左到右即可,注意数据范围很大所以我们考虑要使用__int128来处理

void solve(){
   
    cin>>n;
    
    vector<LL> a(n+5);
    
    __int128 res=0;
    
    for(int i=1;i<=n;i++) cin>>a[i];
    
    LL pre=a[1];
    for(int i=2;i<=n;i++){
    	res+=a[i]*pre;
    	pre+=a[i];
    }
    
    function<void(__int128)> print = [&](__int128 res){
    	if(res>9) print(res/10);
    	putchar(res%10+'0');
    };
    
    print(res);
    return ;
}

5.简单的LIS问题

题目意思很简单修改一个数然后为0-10^{100}然后求最长上升子序列,我们可以发现数据范围是

3e3可以使用n^2LIS接着就是找一个数修改 我们明显的可以划分为前面和后面来区别,所以

我们求一个前面的最长上升子序列,倒着求一个最长下降子序列拼接,接着考虑单独的最长子序列操作,对于上升子序列把后面的一个数改成比自己大即可,对于改前面的数就需要注意是不是>0(题目特殊限制)

void solve(){
   
    cin>>n;
    vector<int> a(n+5),dp1(n+5,1),dp2(n+5,1);
    
    for(int i=1;i<=n;i++) cin>>a[i];
    
    for(int i=1;i<=n;i++)
    	for(int j=1;j<i;j++)
    		if(a[j]<a[i]) dp1[i]=max(dp1[i],dp1[j]+1);
    
    for(int i=n;i>=1;i--)
    	for(int j=n;j>i;j--)
    		if(a[i]<a[j]) dp2[i]=max(dp2[i],dp2[j]+1);
    
    int ans=dp1[n];
    for(int i=1;i<=n;i++){
    	for(int j=i+2;j<=n;j++){
    		if(a[i]<=a[j]-2){
    			ans=max(ans,dp1[i]+dp2[j]+1);
    		}
    	}
    	if(i!=n) ans=max(ans,dp1[i]+1);
    	if(i!=1 && a[i]!=0) ans=max(ans,dp2[i]+1);
    }
    
    cout<<ans<<endl;
    	
    
    return ;
}

考虑提升数据范围就使用nlogn同时需要存在来这个时候的最大或者最小值以及数量

void solve(){
   
    cin>>n;
    
    vector<int> a(n),A(n),B(n),cp(n),cl(n);
    
    for(auto&v:a) cin>>v;
   
    vector<int> pre,last;
    
    for(int i=0;i<n;i++){
        int v=a[i];
        if(pre.empty()||v>pre.back()) pre.push_back(v);
        else pre[lower_bound(pre.begin(),pre.end(),v)-pre.begin()]=v;
        A[i]=pre.back();// 表示到这个点的时候的最大值是多少
        cp[i]=pre.size();// 表示到这个点的时候最长上升子序列的长度都是多少
    }
    
    reverse(a.begin(),a.end());
    
    int ans=pre.size();
    
    for(int i=0;i<n;i++){
        int v=a[i];
        if(last.empty()||v<last.back()) last.push_back(v);
        else last[lower_bound(last.begin(),last.end(),v,greater<int>())-last.begin()]=v;
        B[n-i-1]=last.back();//表示到这个点的最小值是多少
        cl[n-i-1]=last.size();// 表示这个点的长度是多少
    }
    
    
    for(int i=0;i<n-1;i++){
        if(i && A[i-1]<=B[i+1]-2){
            ans=max(ans,cp[i-1]+cl[i+1]+1);
        }
        ans=max(ans,cp[i]+1);
        if(i && B[i]!=0) ans=max(ans,cl[i]+1);
    }
    
    cout<<ans<<endl;
    return ;
}

6.期望次数

我们可以知道和是一个概率dp,依照题目意思我们定义状态为当前 为x是期望为dp[x](x==i)

1.当i>=m 时 dp[i]=0;

2.当i<m时  dp[i]=1+\frac{\sum_{j=1}^{n} a_j * dp[i*j](i*j<m))}{sum}

进行变形之后得到答案dp[i]=\frac{(sum+\sum_{j=1}^{n}a_j*dp[i*j](i*j<m)))}{sum-a[1]}

其中sum是a_i之和,接着就可以按照公式倒着递推即可(注意逆元之类的操作)

LL qmi(LL a,LL b,LL p){
	LL res=1;
	while(b){
		if(b&1) res=res*a%p;
		b>>=1;
		a=a*a%p;
	}
	return res;
}

LL inv(LL x){
	return qmi(x,mod-2,mod);
}

void solve(){
   
    cin>>n>>m;
    vector<LL> dp(m);
    vector<int> a(n);
    LL sum=0;
    for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];
    for(int i=m-1;i>=1;i--){
    	for(int j=2;j<=n&&i*j<m;j++){
    		dp[i]+=a[j]*dp[i*j];
    		dp[i]%=mod;
    	}
    	(dp[i]+=sum)%mod;
    	dp[i]=dp[i]*inv(sum-a[1])%mod;
    } 
    cout<<dp[1]<<endl;
    return ;
}

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 蓝桥杯单片机11届省第1题目pdf文件是一份包含了本全部考题的pdf文档。该文档一共包含了两个部分:单选题和编程题。单选题主要考察了考生对单片机的基础知识、指令系统及其他相关知识的掌握情况。编程题则主要考察了考生对单片机应用程序开发和编程调试能力的掌握情况。 在单选题部分,考生需要根据题目要求进行选择题作答。这些选择题旨在考察考生的理论知识掌握情况,考查内容包含了单片机内部模块原理、寄存器使用方法、程序设计思路、常用外设接口以及通信协议等。考生需要根据自身的掌握情况进行选择,并将自己的答案填入答题卡中。 在编程题部分,考生需要根据题目要求使用指定的语言和开发工具,编写一定的单片机应用程序,并完成程序调试和验证。考试通过指示灯或者液晶显示屏等方式,展示程序的正确运行情况。编程题考查内容包含了对单片机的开发环境、程序设计流程、编程调试、应用实现逻辑等方面的掌握情况。考生需要具备一定的实操能力,并能够将理论知识与实践能力相结合,顺利完成编程任务。 总的来说,蓝桥杯单片机11届省第1题目pdf文档是一份涉及单片机理论与实践知识的综合性考试文件,对单片机应用程序开发和编程调试水平的考查具有一定的参考意义。 ### 回答2: 蓝桥杯单片机11届省第1题目pdf文件中包含了该的各个题目,共分为基础题、提高题、创意题三个部分。基础题主要考察对单片机编程基础语法和基本知识的掌握程度,内容包括LED灯闪烁、蜂鸣器发声等常见实验,难度逐渐递增。提高题则较为复杂,需考生掌握较深入的单片机编程知识和技巧,例如读写AT24C02芯片、使用定时器、串口通信等。创意题则要求考生要有一定的创意思维和实际操作能力,能够完成较为实用性和创意性的电子设备制作,例如设计简易报警器等。 该份pdf文件还提供了详细的题目描述、给定的测试程序框架和输入输出格式要求等信息,以及需要的元器件或接口要求等内容,有助于考生进行题目的理解和实际操作。这些题目在一定程度上考验了参者的实际动手能力、代码调试能力和解决问题的能力,在实践中提升了考生的编程技能和实用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值