牛客练习赛24

本文解析了六道经典编程题目,包括石子序列、凤凰、PH试纸等,通过示例代码展示了各种算法的应用,如深搜、背包问题及图算法。

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

传送门:点我
A 石子序列
相邻的不同,第一个位置有m种可能,以后的每个位置有m-1种可能

#include<iostream>
using namespace std;
#define mod 1000000007
typedef long long ll;
int main(){
    int n,m;
    cin>>n>>m;
    ll sum=m;
    for(int i=1;i<n;i++){
        sum=sum*(m-1);
        sum=sum%mod;
    }
    cout<<sum<<endl;
}

B 凤凰
看根节点的那一个树枝儿孙最多,用深搜,

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000000+100;
int head[maxn],tot;
struct Edge{
    int to,next;
}edge[maxn<<1];
void adde(int u, int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
        edge[tot].to=u;
        edge[tot].next=head[v];
        head[v]=tot++;
}
int son[maxn];
int Max;
void DFS(int u,int fa){
    son[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next){
        Edge e=edge[i];
        int v=e.to;
        if(v==fa) continue;
        DFS(v,u);
        son[u]+=son[v];
        if(u==1) Max=max(Max,son[v]);
    }
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        head[i]=-1;
    }
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        adde(u,v);
    }
    DFS(1,-1);
    printf("%d\n",Max);
}

C PH 试纸
直接开两个数组分别记录位置

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1000000+10;
int r[maxn],b[maxn];
int main(){
    int n,m;
     
    scanf("%d%d",&n,&m);
    
    char str[maxn];
    getchar();
    scanf("%s",str+1);
    getchar();
    int countr=1;
    int countb=1;
    for(int i=1;i<=n;i++){
        if(str[i]=='R'){
            r[countr++]=i;
        }
        else{
            b[countb++]=i;
        }
    }
    char ch;
    int lin;
    for(int i=0;i<m;i++){
        scanf("%c %d",&ch,&lin);
        getchar();
        if(ch=='R'&&r[lin]!=0){
            printf("%d\n",r[lin]);
        }
        else if(ch=='R'&&r[lin]==0){
            printf("-1\n");
        }
        else if(ch=='B'&&b[lin]!=0){
            printf("%d\n",b[lin]);
        }
        else{
            printf("-1\n");
        }
    }
}

D 插排树
深搜

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=50000+100;
int head[maxn],tot;
struct Edge{
    int to,next;
}edge[maxn];
int dis[maxn],len[maxn];
int Max;
int du[maxn];
void DFS(int u,int fa){
    for(int i=head[u];i!=-1;i=edge[i].next){
        Edge e=edge[i];
        int v=e.to;
        if(v==fa) continue;
        dis[v]=dis[u]+len[v];
        DFS(v,u);
        Max=max(Max,dis[v]);
    }
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) head[i]=-1;
    for(int i=1;i<n;i++){
        int u,v,c;
        scanf("%d%d%d",&u,&v,&c);
        edge[tot].to=u;
        edge[tot].next=head[v];
        head[v]=tot++;
        len[u]=c;
        du[u]++;
    }
    int root;
    for(int i=1;i<=n;i++) if(du[i]==0) root=i;
    dis[root]=0;
    DFS(root,-1);
    printf("%d\n",Max);
}

E 青蛙
直接用dijkstra 最短路跑的

#include <iostream>
using namespace std;
#define MAX 9999999
#define LEN 300
int map[LEN][LEN];    //某点到某点两点间的的距离
int dist[LEN];              //记录当前点到源点的最短路径长度
int mark[LEN];           //加入进来的点的集合
//初始化map为正无穷大
void init(){
       int i,j;
       for(i=0;i<LEN;i++){
              for(j=0;j<LEN;j++){
                     map[i][j]=MAX;
              }
       }
}
//n:多少条路  start:起始点
void myDijstra(int n,int start){
       int i,j,min,k;
       for(i=1;i<=n;i++){
              mark[i]=0;//没有点加入
              dist[i]=map[start][i];//初始
       }
       mark[start]=1;//把起始点加进来
       dist[start]=0;
       for(i=1;i<=n;i++){
              min=MAX;
              for(j=1;j<=n;j++){
                     if(!mark[j] && dist[j]<min){    //取出不在mark里的最小的dist[i]
                            min=dist[j];
                            k=j;//标记
                     }
              }
              if(min==MAX)
                     break;
              mark[k]=1;//把K加进来
              //做松弛操作
              for(j=1;j<=n;j++){
                     if(!mark[j] && dist[j]>dist[k]+map[k][j]){
                            dist[j]=dist[k]+map[k][j];
                     }
              }
       }
}
int main(){
       int i,j,n,line;
       int a,b,d;
       cin>>n>>line;   //输入点和边
       init();
       for(i=0;i<line;i++){
              cin>>a>>b;  //输入各边的权值
              if(map[a][b]>1){
                     map[a][b]=1;
              }
       }
       for(i=0;i<n;i++){
           map[i][i+1]=1;
           map[i+1][i]=1;
       }
       myDijstra(n,0);//调用方法
       
       cout<<dist[n]<<endl;
       return 0;
}

F 三轮
感觉像完全背包,
但是都说正解是分治fft …好吧并不会

#include<iostream>
#include<vector>
using namespace std;
#define mod 19260817
const int maxn=100000+100;
int dp[maxn],ans[maxn];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&ans[i]);
    }
    dp[0]=1;
    for(int i=1;i<=n;i++){
        for(int j=ans[i];j<=m;j++){
            dp[j]=(dp[j]+dp[j-ans[i]])%mod;
        }
    }
    int sum=0;
    for(int i=1;i<=m;i++){
        sum=(sum+dp[i])%mod;
    }
    printf("%d\n",sum);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值