寒假训练赛01补题

寒假训练赛01补题
昨天是寒假训练赛第一场,A了两题,rank34。打的一般。最近做的题确实比较少了,得加强训练。
A.新年礼物
签到+模拟
思路:直接遍历一遍,每次更新手中灯笼的漂亮值和价值,然后计数即可。
代码:

LL p[N],w[N];
void solve(){
    int n;
    cin>>n;
    for(int i=0;i<n;i++) cin>>p[i];
    for(int i=0;i<n;i++) cin>>w[i];
    int cnt=0,cp=p[0],cw=w[0];
    for(int i=1;i<n;i++){
        if(p[i]>cp){
            cp=p[i];
            if(cw>w[i]) cnt++;
            cw=w[i];
        }
    }
    cout<<cnt<<endl;
}

B.灯笼展
题意:对于第i个数,求出前面的数中小于等于该数的第k个数。
思路:因为每次要求的k都是固定的,所以我们只需要去维护第k大的数即可。赛时调试了很久,后面想出直接可以用优先队列(大根堆)去维护即可。
代码:

LL a[N];
void solve(){
    int n,k;
    cin>>n>>k;
    priority_queue<int> q;
    for(int i=0;i<n;i++) cin>>a[i];
    for(int i=0;i<k;i++){
      q.push(a[i]);
      cout<<-1<<endl;
    }
    for(int i=k;i<n;i++){
      if(a[i]>=q.top()) cout<<q.top()<<endl;
      else {
        cout<<-1<<endl;
        q.pop();
        q.push(a[i]);
    }
  }
}

C.新年大礼
二分
题意:在1-n的序列中删去几个值,问你现在第k个数是多少?
思路:二分找出满足 k + p o s > a p o s k+pos>a_{pos} k+pos>apos的最大值。
代码:

void solve(){
    int n,m;
    cin>>n>>m;
    vector<LL> a(n);
    for(int i=0;i<n;i++) cin>>a[i];
    sort(all(a));
    while(m--){
      LL k;
      cin>>k;
      int l=0,r=n;
      while(l<r){
        int mid=l+r>>1;
        if(k+mid+1>a[mid]) l=mid+1;
        else r=mid;
      }
      cout<<k+l<<endl;
    }
}

D.摩天楼
模拟+单链表
题意:给你三种操作1.ADD 加一个数到栈顶 2.REMOVE 去除栈顶的元素(如果还有数的话) 3.LOAD 回到t时刻。

思路:前两种操作只需要去维护单链表尾部的数即可。而第三种操作,我们则需要用一个数组去存每个状态的指针。便于我们回到那个时候。

代码:

struct node{
    int val;
    node *pre;
};
void solve(){
    node *root=new (node){-1,0};
    auto cur=root;
    int n;
    cin>>n;
    vector<node*> a(n+1);
    for(int i=1;i<=n;i++){
        string op;
        int x;
        cin>>op;
        if(op[0]!='R') cin>>x;
        if(op[0]=='A') cur=new (node){x,cur};
        else if(op[0]=='R'){
            if(cur->pre) cur=cur->pre;
        }
        else if(op[0]=='L') cur=a[x];
        a[i]=cur;
        cout<<cur->val<<endl;
    }

}

E.神抽
题意:有n个卡池,每个卡池中有k个(k不同)角色,告诉你每个角色下赛季要去的卡池,如果先抽到任何一个卡池中的任何一个角色x,并且x的下个奖池是y。如果再抽到一个角色z,他的下个奖池也是y。那么定义为神抽。让你求神抽的概率。结果取模。
思路:先统计一下每种值 i i i在角色池中出现的次数 c n t i cnt_i cnti ,假设第一次抽 x x x池中的到 y y y ,那么 y y y对答案的贡献为: 抽到 x x x的概率 × \times × x x x抽到 y y y的概率 × \times ×所有池子中抽 c n t i cnt_i cnti的概率

**注意:**这里概率是分数,对模数取模比较特殊,比如分数 7 8 对 1 e 9 + 7 \frac{7}{8}对1e9+7 871e9+7取模。那么我们就要将 7 8 \frac{7}{8} 87看成 7 ∗ 1 8 7*\frac{1}{8} 781的形式这里的 1 8 \frac{1}{8} 81也就是 8 − 1 8^{-1} 81。这里就要用乘法逆元去计算了。由于模数是一个素数。所以我们可以直接用快速幂和费尔马小定理求逆元。即 a − 1 m o d a^{-1}mod a1mod p= a p − 2 m o d a^{p-2}mod ap2mod p

代码:

//快速幂 a^b mod p
LL qmi(int a, int b, int p)
{
    LL res = 1 % p;
    while (b)
    {
        if (b & 1) res = res * a % p;
        a = a * (LL)a % p;
        b >>= 1;
    }
    return res;
}
void solve(){
    int n;
    cin>>n;
    vector<int> f(1e6+10),cnt(1e6+10);
    for(int i=0;i<n;i++){
        int k;
        cin>>k;
        for(int j=0;j<k;j++){
            int a;
            cin>>a;
            cnt[a]++;
            f[a]=(f[a]+qmi(n,mod-2,mod)*qmi(k,mod-2,mod)%mod)%mod;
        }
     }
     LL ans=0;
     for(int i=1;i<=1e6;i++){
        ans=(ans+f[i]*qmi(n,mod-2,mod)*cnt[i]%mod)%mod;
     }
     cout<<ans<<endl;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Showball.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值