牛客练习赛第24场

A_石子序列:

这个题和BZOJ的越狱一模一样,就是简单的组合数学问题。

一排石子,第一个可以有M种选择,第二个有M-1种选择,然后后面的以此都是那样。

这个题目唯一的考点可能就是快速幂吧。

ans= M* qpow( M - 1 , N- 1 );

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
template <class T>
void read( T & x){
    x=0;ll f=1;char c=getchar();
    for( ; !isdigit(c); c=getchar()){ if(c=='-') f=-1;}
    for( ;  isdigit(c); c=getchar()){ x=x*10+c-'0';}
}
ll qpow(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1){
            ans=ans*a%mod;
        }
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
int main()
{
    ll n,m;
    read(n),read(m);
    ll ans=(m*qpow(m-1,n-1))%mod;
    printf("%lld\n",ans);
}

B_凤凰:

这个题目真的有意思,我想了一会,不太好想,因为我想到可能和某个位置的子节点个数有关吧,

后来看了题解,联系了出题人,问了一波,我就发现这个题真的挺好想的。

首先容易证明每一只鸟可能会在排队,

如果没有排队那么说明此时它的子节点都是没有鸟的。

然后一秒都有根节点相连的节点个数K,每秒都有K只输送,

然而K关键不是看总个数,而是关注在过来时候受限制的位置。

所以影响时间的因素关键是:与1(根节点)相连的子树大小。

然而我在看正确的代码中出现了我没讲过的骚操作。

首先贴上代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
template <typename T>
void read(T &x){
    x=0;int f=1;char c=getchar();
    for(; !isdigit(c);c=getchar()) {if(c=='-') f=-1;}
    for(;  isdigit(c);c=getchar()) {x=x*10+c-'0';}
}
vector <int>G[N];
int n,x,y;
int dfs(int x,int pre=1){
    int cnt=1;
    for(auto &to:G[x]){
        if(to!=pre){
            cnt+=dfs(to,x);
        }
    }
    return cnt;
}
int main()
{
    read(n);
    for(int i=1;i<=n-1;i++){
        read(x);read(y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    int ans=0;
    for(auto & to:G[1]){
        ans=max(ans,dfs(to));
    }
    return 0*printf("%d\n",ans);
}

 其中for( auto & v :G[  x  ] )意思是

        for(   int i = 0; i< G[x] .size ();i++){

                      auto  v=G[ x ][ i ];

          }

还有自己看出来的并查集找子树。

#include<bits/stdc++.h>
using namespace std;
const int N=1000050;
template<class T>
void read(T& x){
    x=0;int f=1;char c=getchar();
    for(; !isdigit(c);c=getchar()){ if(c=='-'){f=-1;}}
    for(;  isdigit(c);c=getchar()){ x=x*10+c-'0';}
}
int pre[N];
int fa(int x){ return pre[x]==x?x:pre[x]=fa(pre[x]);}
void Union(int x,int y){ x=fa(x);y=fa(y);pre[x]=y;}
int x,y,n,fu,fv;
int ans=0,cnt[N];
int main()
{
    read(n);
    for(int i=1;i<=n;i++){
        pre[i]=i;
    }
    for(int i=1;i<=n-1;i++){
        read(x);read(y);
        if(x!=1&&y!=1){
            x=fa(x),y=fa(y);
            pre[x]=y;
        }
    }
    /*for(int i=1;i<=n;i++){
        printf("%d %d\n",i,pre[i]);
    }*/
    for(int i=1;i<=n;i++){
        ++cnt[fa(i)];
    }
    for(int i=1;i<=n;i++){
        ans=max(ans,cnt[i]);
    }
 
    printf("%d\n",ans);
    return 0;
}

C—PH 试纸

简单的模拟询问题,只要开两个数组,把对应的位置记录即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000005;
template <class T>
void read(T &x){
    int f=1;char c=getchar();
    for( ; !isdigit(c); c=getchar()) {if(c=='-') f=-1;}
    for( ;  isdigit(c); c=getchar()) { x=x*10+c-'0';}
}
int R[N],B[N];
char s[N],c;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    memset(R,-1,sizeof(R));
    memset(B,-1,sizeof(B));
    int cntR=0,cntB=0;
    scanf("%s",s);
    for(int i=0;i<n;i++){
        if(s[i]=='R') R[++cntR]=i+1;
        else          B[++cntB]=i+1;
    }
    //printf("%s\n",s+1);
    int t;
    for(int i=1;i<=m;i++){
        scanf("%s%d",s,&t);
        if(s[0]=='R')
            printf("%d\n",R[t]);
        else
            printf("%d\n",B[t]);
    }
    return 0;
 
}

D—插排树

这个题目就是考查你会不会把最短路的模板改成最长路罢了。

我的做法:模板Dijstra 堆优化。

#include<bits/stdc++.h>
using namespace std;
const int N=50050;
template <class T>
void read(T &x){
    x=0;int f=1;char c=getchar();
    for( ; !isdigit(c);c=getchar()){ if(f=='-') f=-1;}
    for( ;  isdigit(c);c=getchar()){ x=x*10+c-'0';}
}
typedef struct node{
    int to,w,next;
}Edge;
Edge edge[N];
int head[N],cnt,dis[N],ans=-1;
void add_edge(int u,int v,int w){
    edge[cnt].to=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
struct Cmp{
    bool operator ()(int a,int b){
        return dis[a]>dis[b];
    }
};
void dijstra(int S){
    memset(dis,128,sizeof(dis));
    dis[S]=0;
    priority_queue<int,vector<int> ,Cmp >q;
    q.push(S);
    while(!q.empty()){
        int cur=q.top();
        q.pop();
        for(int i=head[cur];~i;i=edge[i].next){
            int to=edge[i].to;
            int w=edge[i].w;
            if(dis[to]<dis[cur]+w){
                dis[to]=dis[cur]+w;
                ans=max(dis[to],ans);
                q.push(to);
            }
        }
    }
    printf("%d\n",ans);
}
int n,du[N],x,y,w;
int main()
{
    memset(du,0,sizeof(du));
    memset(head,-1,sizeof(head));
    read(n);
    for(int i=1;i<=n-1;i++){
        read(x),read(y),read(w);
        add_edge(y,x,w);
        du[x]++;
    }
    /*for(int i=1;i<=n;i++){
        if(du[i]==0){
            printf("####%d\n",i);
        }
    }*/
    for(int i=1;i<=n;i++){
        if(du[i]==0){
            dijstra(i);break;
        }
    }
 
    return 0;
}

E——青蛙

这个题挺有意思的,本来是DP写的,由于时间关系,我到时肯定会贴回来的DP做法。

然后我的做法是建边跑一个SPFA。

#include<bits/stdc++.h>
using namespace std;
const int N=505;
template <class T>
void read( T &x){
    x=0;int f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()){if(c=='-')f=-1;}
    for(; isdigit(c);c=getchar()){x=x*10+c-'0';}
}
int L,n,cnt,x,y,w,dis[N],vis[N],head[N];
typedef struct Edge{
    int to,next,w;
}Edge;
Edge e[N];
void add_edge(int u,int v,int w=1){
    e[cnt].to=v;
    e[cnt].next=head[u];
    e[cnt].w=1;
    head[u]=cnt++;
}
void SPFA(int S){
    memset(dis,127,sizeof(dis));
    vis[S]=1;
    dis[S]=0;
    queue<int>q;
    q.push(S);
    while(!q.empty()){
        int cur=q.front();
        q.pop();
        vis[cur]=0;
        for(int i=head[cur];~i;i=e[i].next){
            int to=e[i].to,w=e[i].w;
            if(dis[to]>dis[cur]+w){
                dis[to]=dis[cur]+w;
                if(vis[to]==0){
                    vis[to]=1;
                    q.push(to);
                }
            }
        }
    }
    printf("%d\n",dis[L]);
}
int main()
{
    memset(head,-1,sizeof(head));
    read(L),read(n);
    for(int i=0;i<=L-1;i++){
        add_edge(i,i+1);
        add_edge(i+1,i);
    }
    for(int i=1;i<=n;i++){
        read(x),read(y);
        add_edge(x,y);
    }
    SPFA(0);
    return 0;
}

F——三轮

压轴题:考察了FFT来优化。但是我不会,所以给自己挖一个坑,当我会的时候就是我AC的时候了。

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值