“统信杯”第十七届黑龙江省大学生程序设计竞赛 AFHIL

news/2024/7/20 22:02:56 标签: 深度优先, 算法, 字符串

A题

在这里插入图片描述

题解

以样例2为例
1
黄色区域为可以容纳下的书, 让我们分开来计算
因为a书不可被减少, 所以a书顶上至少能够装得下 ( n − m ) b ∗ ( h − a ) \frac{(n-m)}{b}*(h-a) b(nm)(ha)
然后再考虑b书头上, 设x为减少的b书
那么b书头上能够容纳 m − x b ∗ ( h − b ) \frac{m-x}{b}*(h-b) bmx(hb)
根据样例很明显a书在装了 ( n − m ) b ∗ ( h − a ) \frac{(n-m)}{b}*(h-a) b(nm)(ha)本b书后可能还会存在空位, 此时可以将空位让给b书, 所以b书头上可以多计算a书剩下装不下b书的区域, 这个多出来的区域就是 n − ( n − m ) b ∗ b n-\frac{(n-m)}{b}*b nb(nm)b
最后得到b头上的结果为 m − x + n − ( n − m ) b ∗ b b ∗ ( h − b ) \frac{m-x+n-\frac{(n-m)}{b}*b}{b}*(h-b) bmx+nb(nm)b(hb)

而这个x要怎么得到, 很明显x可以二分答案

代码

bool check(ll x)
{
    ant=((m-x+n-n/b*b)/b)*(k-b);//b能容纳多少本书
    return (cnt+ant)>=x;
}

void solve()
{
    cin>>a>>b>>n>>m>>k;
    ans=n+m;
    cnt=(n/b)*(k-a);//能放cnt本b书
    ll l,r;
    l=0,r=m-1;
    while(l<=r)
    {
        ll mid=l+r+1>>1;
        if(check(mid)) 
        {
            l=mid+1;
            ans=mid;
        }
        else r=mid-1;
    }
    l=max(l-1,0);
    cout<<n+m-l<<endl;
    return;
}

F题

在这里插入图片描述
在这里插入图片描述

题解

签到题没什么好解释的, 感觉自己写的dfs还复杂了点
这题甚至可以直接打表, 毕竟能走的路径就那么点

代码

 
void dfs(ll a,ll b,ll w)
{
    if(a==b)
    {
        ans=min(ans,w);
        return;
    }
    f[a]=1;
 
    if(a==1)
    {
        cnt=2;
        if(f[cnt]==0) dfs(cnt,b,w+1);
        cnt=3;
        if(f[cnt]==0) dfs(cnt,b,w+1);
    }else if(a==2)
    {
        cnt=1;
        if(f[cnt]==0) dfs(cnt,b,w+1);
        cnt=4;
        if(f[cnt]==0) dfs(cnt,b,w+1);
    }else if(a==3)
    {
        cnt=1;
        if(f[cnt]==0) dfs(cnt,b,w+1);
        cnt=4;
        if(f[cnt]==0) dfs(cnt,b,w+1);
    }else if(a==4)
    {
        cnt=2;
        if(f[cnt]==0) dfs(cnt,b,w+1);
        cnt=3;
        if(f[cnt]==0) dfs(cnt,b,w+1);
        cnt=5;
        if(f[cnt]==0) dfs(cnt,b,w+1);
        cnt=6;
        if(f[cnt]==0) dfs(cnt,b,w+1);
    }else if(a==5)
    {
        cnt=7;
        if(f[cnt]==0) dfs(cnt,b,w+1);
        cnt=4;
        if(f[cnt]==0) dfs(cnt,b,w+1);
    }else if(a==6)
    {
        cnt=7;
        if(f[cnt]==0) dfs(cnt,b,w+1);
        cnt=4;
        if(f[cnt]==0) dfs(cnt,b,w+1);
    }else
    {
        cnt=5;
        if(f[cnt]==0) dfs(cnt,b,w+1);
        cnt=6;
        if(f[cnt]==0) dfs(cnt,b,w+1);
    }
 
    f[a]=0;
}
 
 
void solve()
{
    ll x,y,a,b,ans1,ans2;
    cin>>a>>b>>x>>y;
    ans=INF;
    ans1=ans2=0;
    dfs(a,x,0);
    ans1+=ans;
    ans=INF;
    dfs(b,y,0);
    ans1+=ans;
 
    ans=INF;
    dfs(a,y,0);
    ans2+=ans;
    ans=INF;
    dfs(b,x,0);
    ans2+=ans;
    
    cout<<min(ans1,ans2)<<endl;
    return;
}

H题

在这里插入图片描述

题解

这不括号配对吗, 几年没见怎么变省赛题了

遇到(不输出, 遇到-直接输出当前下标, 遇到)先输出当前下标然后输出上一个(的下标
感觉比括号配对还简单

代码

void solve()
{
    cin>>n;
    cin>>str;
    stack<ll>s;
    str=" "+str;
    rep(i,1,n)
    {
        if(str[i]=='-') cout<<i<<' ';
        else if(str[i]==')') 
        {
            cout<<i<<' ';
            cout<<s.top()<<' ';
            s.pop();
        }
        else if(str[i]=='(') s.push(i);
    }
    return;
}

I题

在这里插入图片描述

题解

一开始还想了会, 看到数据范围直接爆搜
就是爆搜板子, 比搜有多少种排列还简单

代码

void dfs(ll x)
{
    if(x==n)
    {
        ans++;
        return;
    }

    ll it=n-x;
    rep(i,1,it)
        dfs(x+i);
}

void solve()
{
    cin>>n;
    dfs(0);
    cout<<ans<<endl;
    return;
}

L. Let’s Swap

在这里插入图片描述
这题把我折磨麻了, 不是t14就是t15的

题解

官方提解说 字符串哈希能写, kmp能写
然后我就用了find函数, 一直t改成kmp才过了, 麻了

两种操作, 连续使用一种操作就会使得字符串变过去又变回来, 所以只能交替使用两种操作
交替使用两种操作会发现实质上前面l1个字符串移动到了最后面 (默认l1比l2小)
所以只要将a字符串自加变成a+=a后在a中寻找b字符串就行了 (注意b字符串翻转后在a字符串内也算)
最后判断一下b字符串在a中移动的步数是否合法, 如果合法就yes反之no

在a中寻找字符串的操作不能用find!!!必须要用kmp算法, 不然会超时

代码

inline void getNext(int m){
	int j = 0;
	kmp_next[0] = 0;
	for(int i=1; i<m; ++i)
    {
		while(j>0 && b[i]!=b[j]) j=kmp_next[j-1];
		if(b[i]==b[j]) ++j;
		kmp_next[i] = j;
	}
}

inline int kmp(int n,int m){
	int i, j = 0;
	int p = -1;
	getNext(m);
	for(i=0; i<n; ++i){
		while(j>0 && b[j]!=a[i]) j=kmp_next[j-1];
		if(b[j]==a[i]) ++j;
		if(j==m)
        {
			p = i - m + 1;
			break;
		}
	}
	return p;
}

inline void solve()
{
    cin>>a>>b>>x>>y;
    n=a.size();
    a+=a;
    ans=0;
    if(x>y) swap(x,y);
    if(kmp(2*n,n)==-1)
    {
        ans=1;
        reverse(b.begin(),b.end());
    }
    cnt=kmp(2*n,n);
    if(ans&&cnt==-1)
    {
        no
        return;
    }
    if(ans) cnt=abs(cnt-x);
    if(cnt%(__gcd(n,abs(y-x)))) no
    else yes
    
    return;
}

http://www.niftyadmin.cn/n/175874.html

相关文章

Qt/PyQt多线程

Qt提供了跨平台的线程支持&#xff0c;其中包括线程类、线程安全的事件发布机制以及支持线程间信号槽连接的特性。这些功能可以帮助开发者轻松地开发可移植的多线程Qt应用程序&#xff0c;并有效利用多处理器系统的资源。此外&#xff0c;多线程编程可以提升应用程序的性能和用…

【LeetCode】《LeetCode 101》第五章:排序算法

文章目录5.1 常用的排序算法1. 快速排序2. 归并排序3. 插入排序4. 冒泡排序5. 选择排序6. 总结5.2 快速选择215. 数组中的第K个最大元素&#xff08;中等&#xff09;5.3 桶排序347. 前 K 个高频元素&#xff08;中等&#xff09;5.4 练习451. 根据字符出现频率排序&#xff08…

Kotlin语法-Day4

文章目录1.1 apply内置函数1.2 let内置函数1.3 run内置函数1.4 with内置函数1.5 also内置函数1.6 takeIf takeUnless1.7 List创建与元素获取1.8 可变List集合1.9 mutator1.10 List集合遍历1.1 apply内置函数 1.apply函数始终返回当前对象本身 2.apply函数 匿名函数持有的是 thi…

手机订货系统有哪些优势?

随着科技的快速发展&#xff0c;移动技术的普及和互联网的快速普及&#xff0c;越来越多的企业开始使用手机订货系统&#xff0c;以提高效率、降低成本并加快订单处理。手机订货系统提供了更加便捷的订货方式&#xff0c;让企业能够更快地响应客户需求&#xff0c;并更好地控制…

【深度解刨C语言】预处理(全)

文章目录前言一.预处理头文件宏与注释二.详解宏注释字符串里面能用宏吗?空格正确用宏定义语句宏的作用域#和##1.#定义宏的建议三.条件编译1.常量表达式2.多分支3.判断是否被定义4.嵌套指令四.include五.error与pragma预定义符号前言 先来两张图复习一下预处理的基本内容 结…

常见的js加密/js解密方法

常见的js加密/js解密方法 当今互联网世界中&#xff0c;数据安全是至关重要的。为了保护用户的隐私和保密信息&#xff0c;开发人员必须采取适当的安全措施。在前端开发中&#xff0c;加密和解密技术是一种常见的数据安全措施&#xff0c;其中 JavaScript 是最常用的语言之一。…

《高质量C/C++编程》读书笔记二

文章目录前言三、命名规则四、表达式和基本语句if语句循环语句五、常量前言 这本书是林锐博士写的关于C/C编程规范的一本书&#xff0c;我打算写下一系列读书笔记&#xff0c;当然我并不打算全盘接收这本书中的内容。   良好的编程习惯&#xff0c;规范的编程风格可以提高代码…

C#中关于事件的讲解

1&#xff1a;什么是事件?在文档是这样定义的&#xff0c;事件就是一种使对象或者类能够提供通知的的成员&#xff0c;就是对象或者类具备了通知的能力。&#xff08;闹钟响了给起床了这个事件告诉我们 谁通知了这个事件&#xff08;闹钟&#xff09;通知了谁&#xff08;我&a…