首页 > 其他分享 >2.5 蓝桥杯练习4题

2.5 蓝桥杯练习4题

时间:2024-02-06 22:33:24浏览次数:35  
标签:const 蚂蚁 int 练习 long 蓝桥 dp 包子 2.5

2.5 蓝桥杯练习4题

昨天忘记写题解啦,今天补上。

1.[P8687 蓝桥杯 2019 省 A] 糖果

题意:糖果店的老板一共有 \(M\) 种口味的糖果出售。为了方便描述,我们将 \(M\) 种口味编号 \(1\) ∼ \(M\)。

小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而是 \(K\) 颗一包整包出售。

幸好糖果包装上注明了其中 \(K\) 颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。

给定 \(N\) 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。

思路:看到数据范围只有\(20\),这不是妥妥的状压\(dp\)?\(dp[i]\)表示达到状态\(i\)最少要买多少包。

先预处理出能满足的状态\(h\),置\(dp[h] = 1\)。

然后转移方程:\(dp[i|a[j]] = min(dp[i|a[j]],dp[i]+1)\)

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int n,m,k;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    cin>>n>>m>>k;
    ll dp[1<<m],a[n];
    memset(dp,127,sizeof(dp));
    for(int i = 1;i <= n; i++)
    {
        int h = 0;
        for(int j = 1;j <= k; j++)
        {
            int x; cin>>x;
            x--;
            h |= (1<<x);            
        }
        dp[h] = 1;
        a[i] = h;
    }

    for(int i = 0;i < (1<<m); i++)
    {
        for(int j = 1;j <= n; j++)
        {
            if(dp[i] < (1<<30))
                dp[i|a[j]] = min(dp[i|a[j]],dp[i]+1);
        }
    }

    if(dp[(1<<m)-1] >= 1<<30)cout<<-1<<"\n";
    else cout<<dp[(1<<m)-1]<<"\n";

    return 0;
}

2.[P8611 蓝桥杯 2014 省 AB] 蚂蚁感冒

题意:长 \(100\) 厘米的细长直杆子上有 \(n\) 只蚂蚁。它们的头有的朝左,有的朝右。

每只蚂蚁都只能沿着杆子向前爬,速度是 \(1\) 厘米 / 秒。

当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。

这些蚂蚁中,有 \(1\) 只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。

请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。

思路:又来到咱们经典的蚂蚁题了。两个蚂蚁相碰会掉头,这个其实我们不用考虑掉头,我们可以当作是两只蚂蚁交换位置然后朝着原方向走。那么有多少只会被感染呢?我们以被感染的朝着左边走为例。那么该只蚂蚁左边的与它方向相反的所有蚂蚁都会被感染,它右边的和它方向相同的蚂蚁都会被感染。

注意:特别的,如果被感染的蚂蚁在两端,且朝着它的那端走的话就只有它自己,因为它不会掉头了,另一边也就不用考虑啦。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 100;
struct node
{
    int dist,dir;
}a[N];

bool cmp(node a,node b)
{
    return a.dist<b.dist;
}

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int n; cin>>n;
    for(int i = 1;i <= n; i++)
    {
        int x; cin>>x;
        a[i].dist = abs(x),a[i].dir = (x>0?1:-1);
    }
    int ill = a[1].dist,d = a[1].dir;
    sort(a+1,a+1+n,cmp);
    int k = 1;
    for(int i = 1;i <= n; i++)
    {
        if(a[i].dist == ill)
        {
            k = i;
            break;
        }
    }
    int cnt = 0;

    if(d < 0)//左
    {
        for(int i = 1;i <= k-1; i++)
            cnt += (d !=a[i].dir);
        
        if(cnt){//!!!小心这里
             for(int i = k + 1;i <= n; i++)
                cnt += (d == a[i].dir);
        }
    }
    else
    {
        for(int i = k + 1;i <= n; i++)
            cnt += (d != a[i].dir);
       
        if(cnt){
            for(int i = 1;i <= k-1; i++)
                cnt += (d == a[i].dir);
        }
        
    }
    cout<<cnt+1<<"\n";
    return 0;
}

3.[P8638 蓝桥杯 2016 省 A] 密码脱落

题意:X 星球的考古学家发现了一批古代留下来的密码。

这些密码是由 A、B、C、D 四种植物的种子串成的序列。

仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的回文串)。

由于年代久远,其中许多种子脱落了,因而可能会失去镜像的特征。

你的任务是:

给定一个现在看到的密码串,计算一下从当初的状态,它要至少脱落多少个种子,才可能会变成现在的样子。

思路:其实很简单,我们只要把原串\(s\)反转一下变成\(t\),求\(s\)和\(t\)的最长回文子串的长度,然后用\(n-最长回文子串的长度\)就是答案啦。这里求最长回文子串的长度我用的是记忆化搜索的版本。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e3 + 10;
int f[N][N],n,m;
string s,t;
int lcs(int i,int j)
{
    if(f[i][j] != -1)return f[i][j];
    if(i==0||j==0)return 0;
    else if(s[i]==t[j])f[i][j] = lcs(i-1,j-1) + 1;
    else f[i][j] = max(lcs(i,j-1),lcs(i-1,j));
    return f[i][j];
}

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    cin>>s;
    t = s;
    n = s.size();
    reverse(t.begin(),t.end());
    s = "?" + s,t = "?" + t;
    memset(f,-1,sizeof(f));
    cout<<n-lcs(n,n)<<"\n";

    return 0;
}

4.[P8646 蓝桥杯 2017 省 AB] 包子凑数

题意:小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有 \(N\) 种蒸笼,其中第 \(i\) 种蒸笼恰好能放 \(A_i\) 个包子。每种蒸笼都有非常多笼,可以认为是无限笼。

每当有顾客想买 \(X\) 个包子,卖包子的大叔就会迅速选出若干笼包子来,使得这若干笼中恰好一共有 \(X\) 个包子。比如一共有 \(3\) 种蒸笼,分别能放 \(3\) 、 \(4\) 和 \(5\) 个包子。当顾客想买 \(11\) 个包子时,大叔就会选 \(2\) 笼 \(3\) 个的再加 \(1\) 笼 \(5\) 个的(也可能选出 \(1\) 笼 \(3\) 个的再加 \(2\) 笼 \(4\) 个的)。

当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有 \(3\) 种蒸笼,分别能放 \(4\) 、 \(5\) 和 \(6\) 个包子。而顾客想买 \(7\) 个包子时,大叔就凑不出来了。

小明想知道一共有多少种数目是包子大叔凑不出来的。

思路:由裴蜀定理可知\(ax+by = c\)。如果\(c = t\times\gcd(a,b)\)。只有\(\gcd(a,b)=1\)的时候才能表示所有的数。那么我们可以求一下所有数的\(\gcd\)的多少,如果不是\(1\),那么答案就是\(INF\)。那么对于是\(1\)的情况,有多少是不能表示的呢?这里可以用完全背包啦。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int a[N],dp[N],V = 1e4;
int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int n; cin>>n;
    for(int i = 1;i <= n; i++)
        cin>>a[i];
    sort(a+1,a+1+n);
    //ax + by = gcd(a,b);
    int g = a[1];
    for(int i = 1;i <= n; i++)
    {
        g = __gcd(g,a[i]);
    }
    if(g != 1)cout<<"INF\n";
    else{
        dp[0] = 1;
        for(int i = 1;i <= n; i++)
        {
            for(int j = a[i];j <= V; j++)
            {
                dp[j] = max(dp[j],dp[j-a[i]]);
            }
        }
        int cnt = 0;
        for(int i = 1;i <= V; i++)
        {
            if(!dp[i])cnt++;
        }
        cout<<cnt<<"\n";
    }
    return 0;
}

标签:const,蚂蚁,int,练习,long,蓝桥,dp,包子,2.5
From: https://www.cnblogs.com/nannandbk/p/18010381

相关文章

  • C++编程练习||1.排序函数模板2.函数模板3.重载printArray函数模板
    1.排序函数模板已知主函数如程序后缀代码所示,请为其编写适当的模板函数,使主函数的bubbleSort函数可以对一个整型数组和一个浮点数数组进行输入、排序、输出操作。#include<iostream>#include<iomanip>usingnamespacestd;template<typenameT>voidbubbleSort(T*arr,......
  • 问题:深蹲动作模式,练习中双脚支撑的宽度是怎么样的?
    问题:深蹲动作模式,练习中双脚支撑的宽度是怎么样的?参考答案如图所示......
  • JVS物联网、低代码、规则引擎2.5功能新增说明
    物联网更新功能新增:1、新增离线存储-页面配置及指令下发对接;用户可以对平台的页面进行自定义配置,通过平台,可以将指令下发给与之相连的设备或系统,这些指令可以是控制指令、配置指令或其他类型的指令。2、新增数据压缩-页面配置及指令下发对接;用户可以对数据压缩的相关参数进行设置,......
  • 2.5 響け恋の歌 ——ARC107~109
    我猜是小小恋歌赞助了这个系列!由于懒得再把细节回想一遍所以会比较概括。但是总体做法保真。ARC107DNumberofMultisets考虑DP:\(f(i,j)\)表示\(i\)个数凑成\(j\)的方案数。那么我们可以枚举最大数的幂次,容易发现只是\(O(\logn)\)的。然后枚举了之后发现是一个类似......
  • C++编程练习||实现分数类Fraction1、实现分数的+,-,*,/ 2、逻辑运算==、!=、<、<=、>、>
    题目:实现分数类Fraction  classFraction{   intnumerator,denominator;   public:   ....  };  要求:1、实现分数的+,-,*,/2、逻辑运算==、!=、<、<=、>、>=6种运输符号。3、实现输出<<,输入 >>操作符重载。  样例1输入:   12 ......
  • 牛客比赛2.5
    比赛链接9题,就看结果来说还是不错的,但是过程我是很不满意的。。A,B签到题,没什么说的必要。C题,数据结构题,很烦,trie树带查询,码起来有些麻烦,考试的时候没有开。其实思路很简单,用01trie树,对每一个点,查找比他小的和它异或起来最大的数字,这个东西在trie树上就是一个贪心,O(logn)级别......
  • 闲话2.5
    haosen我曺檷嘜,你他妈咋回家了......
  • 2.5闲话 & solution 『那是万物伊始的来途/或百川竞流的归处』
    哈哈哈我垫底了,为啥数据这么水啊哈哈我似乎发现很多人当OIer之前都没有一个稳定的网名solution-初三年前模拟测试3初三年前模拟测试3看沧海(桑田变幻)造多少(地覆天翻)似你我(进化简繁)该如何(才得一探)《普及难度》指T4动态开点李超线段树/凸壳又是一坨史,那场ABC是......
  • 2024.2.5寒假每日总结27
    LeetCode跳跃游戏VI1696.跳跃游戏VI-力扣(LeetCode)题目描述给你一个下标从0开始的整数数组nums和一个整数k。一开始你在下标0处。每一步,你最多可以往前跳k步,但你不能跳出数组的边界。也就是说,你可以从下标i跳到[i+1,min(n-1,i+k)]包含两个端点的任......
  • 寒假day4 2.5
    讲师:钟皓曦,NOI2012Au,from成都七中dp树形dp核心:在树上做的dp给定一棵\(n\)个点的树,求这棵树有几个点。对于树形dp,第一个维度是\(f_i\),代表以\(i\)为根的子树内的信息(有几个点)树形dp的转移方法是把所有儿子信息整合所有儿子的dp值\(\rightarrow\)自己。转移:\(......