首页 > 其他分享 >2.1 蓝桥杯练习5题

2.1 蓝桥杯练习5题

时间:2024-02-01 23:11:55浏览次数:34  
标签:const val int ll 练习 long 蓝桥 2.1 id

2.1 蓝桥杯练习5题

1.[P8623 蓝桥杯 2015 省 B] 移动距离

题意:X 星球居民小区的楼房全是一样的,并且按矩阵样式排列。其楼房的编号为 $1,2,3, \cdots $ 。

当排满一行时,从下一行相邻的楼往反方向排号。

比如:当小区排号宽度为 \(6\) 时,开始情形如下:

1  2  3  4  5  6
12 11 10 9  8  7
13 14 15 .....

我们的问题是:已知了两个楼号 \(m\) 和 \(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 = 2e5 + 10;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int w,m,n; cin>>w>>m>>n;
    int x1 = (m-1) / w ,y1 = m % w;
    int x2 = (n-1) / w ,y2 = n % w;
    // cout<<"("<<x1<<","<<y1<<")"<<"\n";
    // cout<<"("<<x2<<","<<y2<<")"<<"\n";
    if(x1 % 2 == 0)y1 = w - y1 + 1;
    if(x2 % 2 == 0)y2 = w - y2 + 1;

    // cout<<"("<<x1<<","<<y1<<")"<<"\n";
    // cout<<"("<<x2<<","<<y2<<")"<<"\n";
    int ans = abs(x1-x2)+abs(y1-y2);
    cout<<ans<<"\n";

    return 0;
}

2.[P8651 蓝桥杯 2017 省 B] 日期问题

题意:小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在 1960 年 1 月 1 日至 2059 年 12 月 31 日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。

比如 02/03/04,可能是 2002 年 03 月 04 日、2004 年 02 月 03 日或 2004 年 03 月 02 日。

给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

思路:给的格式是AA/BB/CC,那么可以操作的只有前面年份。两种选择加\(19\)或者加\(20\)。弄完之后看年份在不在范围内,之后根据平闰年规则看月和日合不合法即可。

// 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;

bool check(int y,int m,int d){
    if(d<=0)return 0;//特判
    if(m==1||m==3||m==5||m==7||m==8||m==10||m==12){//大月
        if(d<=31)return 1;
    }
    if(m==4||m==6||m==9||m==11){//小月
        if(d<=30)return 1;
    }
    if(m==2){//二月
        if(y%4==0){//闰年
            if(d<=29)return 1;
        }else{//平年
            if(d<=28)return 1;
        }
    }
    return 0;
}

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    string s; cin>>s;

    string a = s.substr(0,2);
    string b = s.substr(3,2);
    string c = s.substr(6,2);

    set<string>st;
    //年月日
    string op1 = "19",op2 = "20";
    string y1 = op1 + a;
    int yy1 = stoi(y1);
    if(1960<=yy1&&yy1<=2059 && check(yy1,stoi(b),stoi(c)))
        st.insert(y1+"-"+b+"-"+c);
    y1 = op2 + a;
    yy1 = stoi(y1);
    if(1960<=yy1&&yy1<=2059 && check(yy1,stoi(b),stoi(c)))
        st.insert(y1+"-"+b+"-"+c);

    //月日年
    y1 = op1 + c;
    yy1 = stoi(y1);
    if(1960<=yy1&&yy1<=2059 && check(yy1,stoi(a),stoi(b)))
        st.insert(y1+"-"+a+"-"+b);
    y1 = op2 + c;
    yy1 = stoi(y1);
    if(1960<=yy1&&yy1<=2059 && check(yy1,stoi(a),stoi(b)))
        st.insert(y1+"-"+a+"-"+b);

    //日月年
    y1 = op1 + c;
    yy1 = stoi(y1);
    if(1960<=yy1&&yy1<=2059 && check(yy1,stoi(b),stoi(a)))
        st.insert(y1+"-"+b+"-"+a);
    y1 = op2 + c;
    yy1 = stoi(y1);
    if(1960<=yy1&&yy1<=2059 && check(yy1,stoi(b),stoi(a)))
        st.insert(y1+"-"+b+"-"+a);

    
    for(auto x : st)
        cout<<x<<"\n";
    return 0;
}

3.[P8637 蓝桥杯 2016 省 B] 交换瓶子

题意:有 \(N\) 个瓶子,编号 \(1 \sim N\),放在架子上。

比如有 \(5\) 个瓶子:

\[2,1,3,5,4 \]

要求每次拿起 \(2\) 个瓶子,交换它们的位置。

经过若干次后,使得瓶子的序号为:

\[1,2,3,4,5 \]

对于这么简单的情况,显然,至少需要交换 \(2\) 次就可以复位。

如果瓶子更多呢?你可以通过编程来解决。

思路:如果当前的瓶子不在该在的位置上,那么我们就把他放在他应该在的位置。如果原本就已经在了,就跳过他。因为每一个数都有一个属于自己的最终位置,所以我们让每一个数换到它最终的位置之后,他就不用再动了。也就是每个数换一次。这样的话时间复杂度是\(O(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 = 2e5 + 10;
int a[N],id[N];
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];
    }

    int cnt = 0;
    for(int i = 1;i <= n; i++)
    {
        if(a[i] != i)
        {
            cnt++;
            for(int j = i+1; j <= n; j++)if(a[j] == i){
                swap(a[i],a[j]);
            }
        }
    }
    cout<<cnt<<"\n";


    return 0;
}

法二:学习的别人的做法,可以把有关系的点进行连边,因为它存在拓扑关系。之后会形成环,答案就是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 = 2e5 + 10;
bool vis[N];
int n,a[N],cnt;
vector<int>e[N];

void dfs(int u,int fa)
{
   // cout<<"u = "<<u<<"\n";
    if(vis[u])return;
    vis[u] = true;
    for(auto v : e[u])
    {
        if(v == fa)continue;
        dfs(v,u);
    }
}

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    cin>>n;
    for(int i = 1;i <= n; i++)
    {
        cin>>a[i];
        if(a[i] != i){
            e[a[i]].push_back(i);
            e[i].push_back(a[i]);
        }
    }

    for(int i = 1;i <= n; i++)
    {
        if(!vis[i])
        {
            dfs(i,0);
            cnt++;
        }
    }
    cout<<n-cnt<<"\n";
    return 0;
}

4.交换瓶子的拓展题——P1327 数列排序

题意:给定一个数列 \(a\),这个数列满足 \(a_i \not =a_j\)(\(i\not=j\)),现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换?

思路:其实和上一题很类似,几乎就一样,但是现在包含负数,数据范围到达了\(1e5\)。

我们可以把记录原数的数值和位置,我们可以把原数的位置看成他们新的数值\(a[i].id\),这样解决了有负数的情况。然后按照数值大小排序,用\(s\)数组记录每个数应该在的位置。然后和上一题类似的,如果它不在自己的位置,我们把当前的数放到他应该放到的位置,直到当前位置对的。因为每一个数都有一个属于自己的最终位置,所以我们让每一个数换到它最终的位置之后,他就不用再动了。也就是每个数换一次。这样的话时间复杂度是\(O(n)\)的。

以样例为例,s数组的情况:

image

// 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;
struct node
{
    int val,id;
}a[N];
int s[N];

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

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].val,a[i].id = i;
    
    
    sort(a+1,a+1+n,cmp);

    for(int i = 1;i <= n; i++)
        s[a[i].id] = i;
    // for(int i = 1;i <= n; i++)
    //     cout<<s[i]<<" ";
    // cout<<"\n";
    int cnt = 0;
    for(int i = 1;i <= n; i++)
    {
        while(s[i] != i)
        {
            swap(s[i],s[s[i]]);
            cnt++;
            // for(int i = 1;i <= n; i++)
            //     cout<<s[i]<<" ";
            // cout<<"\n";
        }
    }
    cout<<cnt<<"\n";

    return 0;
}

其实上面这两个题我一开始想到的是会不会和逆序对有关,但是不对,逆序对是只允许交换相邻两个数,而上面的题没有要求。如果只能交换相邻的,我们可以考虑逆序对的做法。

5.P1908 逆序对

思路:用树状数组,注意要处理有相同数的情况!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5+10;

int n;
struct node
{
    int val,id;
}a[N];
int s[N];

bool cmp(node a, node b)
{
    if(a.val == b.val)
    	return a.id < b.id;
    return a.val < b.val;
}//!注意相等的情况的处理

ll c[N];
ll query(int x){//1...x
	ll s = 0;
	for(;x;x-=x&(-x))
		s += c[x];
	return s;
}
void modify(int x,ll s){//a[x]+=s
	for(;x<=n;x+=x&(-x))
		c[x]+=s;
}

signed main()
{
	cin>>n;
	for(int i = 1;i<=n;i++)
	{
		cin>>a[i].val;
		a[i].id = i;
	}
	sort(a+1,a+1+n,cmp);
	for(int i = 1;i <= n; i++)
		s[a[i].id] = n + 1 - i;

	ll ans = 0;
	for(int i = 1;i <= n; i++)
		ans += query(s[i]),modify(s[i],1);
	cout<<ans<<endl;
	return 0;
}

标签:const,val,int,ll,练习,long,蓝桥,2.1,id
From: https://www.cnblogs.com/nannandbk/p/18002336

相关文章

  • 2024.2.1
    1.继承是java面向对象的一块基石,因为它允许创建分等级层次的类。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同行为。兔子和羊属于食草动物,狮子和豹属于食肉动物类。食草动物和食肉动物又是属于动物类。......
  • 2.1寒假每日总结23
    最最简单的超级马里奥训练过程fromnes_py.wrappersimportJoypadSpaceimportgym_super_mario_brosfromgym_super_mario_bros.actionsimportSIMPLE_MOVEMENTimporttimefrommatplotlibimportpyplotaspltfromstable_baselines3importPPOenv=gym_super_mario......
  • 2.1闲话 - 『奏起我的幻想曲』
    打算换个闲话风格,现在的看起来非常不好今天手滑交了个图片上去卡住了评测集导致被D了漆黑的夜古城之中遗失的传说漆黑的翼苏醒之后陌生的轮廓是谁在我的身后呼唤一时的怔忪是谁在我的心中呼唤为何不将一切掌控快速傅立叶之二我们可以进行卷积的式子标准形......
  • 洛谷 P8687 [蓝桥杯 2019 省 A] 糖果
    题意有\(m\)种口味,每次\(k\)颗一袋出售,给你\(n\)包均为\(k\)颗的糖果,求最少买几袋可以吃到所有口味的糖果。思路暴力对\(n\)包糖果做组合。如果找到其中一种包含了所有口味,将所有满足的方案取糖果包数最小即可。时间复杂度\(\mathcal{O(2^n)}\)。正解考虑状......
  • 2.1
    今天写得有点早,主要经历了一些事情。实际上也没什么不正常的。上午先打\(AC\)自动机,确切的说压根没理解是个什么东西,打病毒这道题,因为没理解费解了好长时间,几乎大半个上午,最后发到博客里请各位大佬指教,恍然大悟。挺尴尬的就把博删了。下午继续搞,先把病毒那题\(A\)了,继续......
  • 2.1
    二月第一天!整个emoji里最抽象的字符串:......
  • Dash 2.15版本新特性介绍
    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/dash-master大家好我是费老师,Dash不久前发布了其2.15.0版本,新增了一些实用的特性,下面我们就来一起get其中的重点......
  • 1.31 蓝桥杯练习5题
    1.31蓝桥杯练习5题退役哩,但是下学期还要打蓝桥。好久没写题脑袋空空,准备每天写几个练手。1.[P8599蓝桥杯2013省B]带分数题意:\(100\)可以表示为带分数的形式:\(100=3+\frac{69258}{714}\)。还可以表示为:\(100=82+\frac{3546}{197}\)。注意特征:带分数中,数字\(1......
  • 2024年1月31日练习答案
    目录P505【基础】寻找祖先P541【基础】吃西瓜(watermelon)P832【提高】AtoBP841【入门】s01串P505【基础】寻找祖先给出充足的父子关系,请你编写程序找到某个人的最早的祖先。规定每个人的名字都没有空格,且没有任意两个人的名字相同。最多可能有1000组父子关系,总人数......
  • 美赛2023C练习-做题笔记
    代码:clc;TC=ProblemCDataWordle;%数据处理noC=TC(:,1);wordC=TC(:,2);dataC=TC(:,3:11);no=cell2mat(noC);data=cell2mat(dataC);L=size(wordC);L=L(1);word=[];%原表格有错误,根据网络数据进行修正wordC{36}="clean";wordC{247}="trash";%修正endfori=1:L......