2019牛客暑期多校训练营(第十场)

本文精选了算法竞赛中的经典题目,包括递归、扩展中国剩余定理、分形图、思维题等,提供了详细的题解思路和代码实现,适合算法学习者深入理解各种算法的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

B 、Coffee Chicken  (递归)

D 、Han Xin and His Troops  (扩展CRT)

E 、Hilbert Sort  (分形图递归)

F、 Popping Balloons  (思维)

H、Stammering Chemists  (水题)


B 、Coffee Chicken  (递归)

题意:

给出两个字符串,按照斐波那契数列进行操作,然后给出一个n和k,计算第n个字符串从第k个开始数数10个并输出,不够就都输出。

分析:

直接dfs即可,还有判断长度1e12后的其实跟前面是一样的。

#include<bits/stdc++.h>

#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pid pair<double,double>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;

const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;

ll a[60];
string s,t;

string dfs(int n,ll k,int cnt){
    if(n==1){
        return s.substr(k-1,min(cnt,(int)s.size()-(int)k+1));
    }else if(n==2){
        return t.substr(k-1,min(cnt,(int)t.size()-(int)k+1));
    }
    if(k<a[n-2]&&k+cnt-1<=a[n-2]) return dfs(n-2,k,cnt);
    else if(k>a[n-2]) return dfs(n-1,k-a[n-2],cnt);
    else return dfs(n-2,k,a[n-2]-k+1)+dfs(n-1,1,cnt-(a[n-2]-k+1));
}

int main(){
    #ifdef io
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif

    a[1]=6;a[2]=7;
    int tot=3;
    for(;;tot++){
        a[tot]=a[tot-1]+a[tot-2];
        if(a[tot]>1e12) break;
    }
    tot++;
    a[tot]=a[tot-1]+a[tot-2];
    s="COFFEE";
    t="CHICKEN";
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        ll k;
        scanf("%d%lld",&n,&k);
        while(n>tot){
            n-=2;
        }
        cout<<dfs(n,k,10)<<endl;
    }
    return 0;
}

D 、Han Xin and His Troops  (扩展CRT)

题意:

很版得题

分析:

非要让我拉个java大数得模板?其实我不想写这个题(在网上抄了一个)。

import java.math.BigInteger;
import java.util.Scanner;
 
 
public class Main {
     
    public static int N = 100010;
    public static BigInteger a[] = new BigInteger[N];
    public static BigInteger m[] = new BigInteger[N];  
    public static int k;
    public static BigInteger mm,xx,yy;
    public static BigInteger exgcd(BigInteger a,BigInteger b){
        if(b.compareTo(BigInteger.ZERO)==0){
            xx=BigInteger.ONE;
            yy=BigInteger.ZERO;
            return a;
        }
        BigInteger z,d=exgcd(b,a.mod(b));
        z=xx;
        xx=yy;
        yy=z.subtract(a.divide(b).multiply(yy));
        return d;
    }
    public  static BigInteger china(){
        BigInteger c,d,ans=a[1],M=m[1];
        for(int i=2;i<=k;i++){
             c=(a[i].subtract(ans.mod(m[i]).add(m[i])).mod(m[i]));
              
             d=exgcd(M,m[i]);
              
             if(c.mod(d).compareTo(BigInteger.ZERO)!=0) return new BigInteger("-1");
             xx=xx.multiply(c.divide(d)).mod(m[i].divide(d));
             ans=ans.add(xx.multiply(M));
             M=M.multiply(m[i].divide(d));
             ans=ans.mod(M).add(M).mod(M);
        }
        return ans;
    }
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in );
        k=cin.nextInt(); mm=cin.nextBigInteger();
        for(int i=1;i<=k;i++){
            m[i]=cin.nextBigInteger();
            a[i]=cin.nextBigInteger();
        }
        BigInteger pm=china(),fu1=new BigInteger("-1");
         
        if(pm.compareTo(fu1)==0) System.out.println("he was definitely lying");
        else if(pm.compareTo(mm)>0) System.out.println("he was probably lying");
        else System.out.println(pm);
    }
     
}

E 、Hilbert Sort  (分形图递归)

题意:

给出一个分形图上点的坐标,然后按照路径排序后输出。

分析:

找出每块之间的关系,然后递归计算即可。

#include<bits/stdc++.h>
 
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pid pair<double,double>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;
 
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
 
ll dfs(int n, ll x, ll y) {
    if(n==0) return 1ll;
    ll m=1ll<<(n-1);
    if (x<=m&&y<=m){
        return dfs(n-1,y,x);
    }
    if(x<=m&&y>m){
        return 3ll*m*m+dfs(n-1,m-(y-m)+1,m-x+1);
    }
    if(x>m&&y<=m) {
        return 1ll*m*m+dfs(n-1,x-m,y);
    }
    if(x>m&&y>m){
        return 2ll*m*m+dfs(n-1,x-m,y-m);
    }
}
 
const int maxn=1e6+10;
 
struct node{
    ll x,y;
    ll id;
    bool operator < (node p){
        return id<p.id;
    }
}p[maxn];
 
int main(){
    #ifdef io
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
 
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++){
        scanf("%lld%lld",&p[i].x,&p[i].y);
        p[i].id=dfs(k,p[i].x,p[i].y);
//        cout<<p[i].x<<" "<<p[i].y<<" "<<p[i].id<<endl;
 
 
    }
    sort(p,p+n);
    for(int i=0;i<n;i++){
        printf("%lld %lld\n",p[i].x,p[i].y);
    }
    return 0;
}

F、 Popping Balloons  (思维)

题意:

有n个气球,现在可以选择射破三行气球和三列气球,而且保证相邻行和列间距相同,问最多能射裂多少气球

分析:

求出横着打和竖着打所有结果,按个数从大到小排序,最大值肯定就从前几大的打法中组合出,

而且取出前四大就可以了(举不出反例,但是我太菜不太会证明),

#include<bits/stdc++.h>

#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pid pair<double,double>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define rush() int T;scanf("%d",&T);while(T--)
#define sc(a) scanf("%d",&a)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;

const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;

//#define gc getchar
char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
inline int read(){
    int ret=0,f=0;char c=gc();
    while(!isdigit(c)){if(c=='-')f=1;c=gc();}
    while(isdigit(c)){ret=ret*10+c-48;c=gc();}
    if(f)return -ret;return ret;
}

const int maxn=1e5+10;

int fx[maxn*3],fy[maxn*3];
struct node{
    int x,y;
    bool operator < (const node p) const {
        return x>p.x;
    }
}a[maxn],w[maxn];

int main(){
    #ifdef io
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif

    int n,r;
    sc(n),sc(r);
    rep(i,1,n){
        scanf("%d%d",&a[i].x,&a[i].y);
        fx[a[i].x]++;
    }
    rep(i,0,1e5){
        w[i].x=fx[i]+fx[i+r]+fx[i+r+r];
        w[i].y=i;
    }
    sort(w,w+maxn);
    int ans=0;
    rep(i,0,100){
        mm(fy,0);
        rep(j,1,n){
            if(a[j].x!=w[i].y&&a[j].x!=w[i].y+r&&a[j].x!=w[i].y+r+r){
                fy[a[j].y]++;
            }
        }
        int res=0;
        rep(j,0,1e5){
            res=max(res,fy[j]+fy[j+r]+fy[j+r+r]);
        }
        ans=max(ans,w[i].x+res);
    }
    printf("%d\n",ans);
    return 0;
}


H、Stammering Chemists  (水题)

太简单就不说了。

#include<bits/stdc++.h>

#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pid pair<double,double>
#define pil pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define E exp(1.0)
//#define io
using namespace std;

const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;

int in[10];
int g[10][10];

int main(){
    #ifdef io
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif

    int T;
    scanf("%d",&T);
    while(T--){
        mm(in,0);
        mm(g,0);
        for(int i=1;i<=5;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            in[u]++;
            in[v]++;
            g[u][v]=1;
            g[v][u]=1;
        }
        int cnt[10]={0};
        rep(i,1,6) cnt[in[i]]++;
        if(cnt[4]){
            printf("2,2-dimethylbutane\n");
        }else if(cnt[3]==2){
            printf("2,3-dimethylbutane\n");
        }else if(cnt[1]==2){
            printf("n-hexane\n");
        }else{
            int tmp;
            rep(i,1,6)if(in[i]==3){
                tmp=i;break;
            }
            int one=0;
            rep(i,1,6){
                if(g[tmp][i]&&in[i]==1) one++;
            }
            if(one==2){
                printf("2-methylpentane\n");
            }else{
                printf("3-methylpentane\n");
            }
        }
    }
    return 0;
}

 

### 2024 暑期训练营 Sort4 题目解析 #### 题目背景与描述 在2024年的暑期训练营中,Sort4是一道涉及字符串排序和字典序比较的题目。该题目的核心在于通过特定的操作改变给定字符串数组的顺序,并最终使得整个序列达到某种最优状态。 #### 解决方案概述 为了有效解决这个问题,需要理解并应用分治算法以及RMQ(Range Minimum Query)技术来优化查询效率[^3]。具体来说: - **初始化阶段**:读入输入数据并将所有字符串存储在一个列表中。 - **预处理部分**:构建笛卡尔树用于快速查找最小值及其位置;同时记录每个节点的信息以便后续更新操作时能够高效定位目标元素的位置。 - 对于每一次交换请求\( (d_i, p_i) \),判断当前待调整项是否满足条件 \( d_i > p_i \)。如果是,则执行相应的移动动作使新的排列更接近理想解; - 使用自定义比较器对修改后的集合重新排序,确保整体结构仍然保持有序特性不变; - 继续上述过程直至完成全部指令集中的每一条命令为止。 ```cpp #include <bits/stdc++.h> using namespace std; struct Node { int val; int idx; }; bool cmp(Node a, Node b){ return a.val < b.val || (a.val == b.val && a.idx < b.idx); } vector<Node> nodes; int n, q; void buildCartesianTree() {/* ... */ } // 执行单步转换操作 void performOperation(int di, int pi) { if(di > pi){ // 当di大于pi时才会引起字典序变化 swap(nodes[di],nodes[pi]); sort(nodes.begin(), nodes.end(),cmp); } } ``` 此段代码展示了如何基于给定条件实施一次有效的变换,并维持全局秩序不受影响。需要注意的是,在实际竞赛环境中可能还需要额外考虑边界情况以及其他潜在陷阱。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值