2024牛客暑期多校训练营1(A,C,H,I)

A

题目大意

选择范围在 [ 1 , 2 m ) [1,2^m) [1,2m)内的任意n个数组成一个长度为n的序列,当且仅当序列序列每个位置上的数均不相等时序列不同,需求得该序列内任意一个子序列满足其所有数的AND后的结果为 1 1 1的序列个数

题解

若一些数的AND后结果为1,需保证其二进制第一位均为1,其他位不全为1,由于题目内每个位置均能填任意数,需要用更宏观的角度来看其位置信息,主要观察的就是

  1. 二进制内如何保证其他位不全为1
  2. 如何去找到这个子序列,同时保证不重复

注意到子序列,可以发现,事实上,对该子序列产生影响的只有奇数,换言之,偶数由于其二进制末位为0,永远不可放入子序列,现在考虑如何考察奇数,并使其不重复。

可以发现,无需考察奇数的子集,故可以考虑奇数的个数,
不妨假设此时考虑的奇数为 k k k个,那么偶数为 n − k n-k nk个,此时固定奇数的位置,其共有 C ( n , k ) C(n,k) C(n,k)个位置可以选择,剩下的均为偶数,考虑偶数的选择,偶数可以任选,故为 ( 2 m − 1 ) n − k (2^{m-1})^{n-k} (2m1)nk个,考虑奇数的选择,奇数需要保证每个二进制位不全为1,就是去除全为1的选择,故为 ( 2 i − 1 ) m − 1 (2^i-1)^{m-1} (2i1)m1

所以最后的答案就是 C ( n , k ) ∗ ( 2 m − 1 ) n − k ∗ ( 2 i − 1 ) m − 1 C(n,k)*(2^{m-1})^{n-k}*(2^i-1)^{m-1} C(n,k)(2m1)nk(2i1)m1

不要忘记在其中取模

代码
import heapq
import sys,math
input=lambda:sys.stdin.readline()
write=lambda x:sys.stdout.write(str(x)+'\n')


def calC_2(n, m, p):
    res = [[0] * (1 + n) for _ in range(1 + n)]
    ## 初始化
    for i in range(1 + n):
        res[i][0] = res[i][i] = 1
    for i in range(2, 1 + n):
        for j in range(i // 2 + 1):
            res[i][j] = (res[i - 1][j - 1] + res[i - 1][j]) % p
            res[i][i - j] = res[i][j]
    return res
n,m,p = map(int,input().split())
rr = calC_2(n,m,p)
res = 0
for i in range(1,n + 1):
    res += (rr[n][i] * (pow(pow(2,n-i,p),m-1,p)) * (pow((pow(2,i,p) - 1),m-1,p)))%p
    res %= p
print(res)代码片

C

题目大意

维护一个序列,每次操作会移除该序列的末尾 t t t个数,同时会往末尾增加一个大小为 v v v的数,询问每次操作后的后缀和总和

题解

直接维护总和,然后每次操作,直接遍历减掉末尾的数乘上它被加的个数 t t t次,最后加入即可

代码
import heapq
import sys,math
input=lambda:sys.stdin.readline()
write=lambda x:sys.stdout.write(str(x)+'\n')


res = 0
nn = 0
temp = []
mod = int(1e9) + 7
for _ in range(int(input())):
    a,b = map(int,input().split())
    for i in range(a):
        tt = temp.pop()
        res -= (nn - i) * tt
        res %= mod
    nn -= a
    nn += 1
    temp.append(b)
    res += b * nn
    res %= mod
    print(res)

H

题目大意

有两场 World Finals 同时举办,每场都有若干出线队伍,两场出线名单
可能有重复的队伍,而一个队伍只能选择其中的一场参加,每场比赛的每支队伍都有一个预测成绩(过题数 + 罚时)
lzr010506 在两场 World Finals 都出线了,他想知道如果所有队伍的最终成绩就是预测成绩,并且可以任意分配两场都出线了队伍的比赛场次的选择,他们队最高可能的排名是多少

题解

模拟,如果lzr010506参加第一场,那么就把可以参加一二场的队伍都放入第二场,同理,如果lzr010506参加第二场,那么就把可以参加一二场的队伍都放入第一场

代码
import heapq
import sys,math
input=lambda:sys.stdin.readline()
write=lambda x:sys.stdout.write(str(x)+'\n')

n = int(input())
tmp1 = []
for i in range(n):
    x = input().split()
    tmp1.append([x[0], int(x[1]), int(x[2])])
tmp2 = []
m = int(input())
for i in range(m):
    x = input().split()
    tmp2.append([x[0], int(x[1]), int(x[2])])
tmp1.sort(key=lambda x: [-x[1], x[2]])
tmp2.sort(key=lambda x: [-x[1], x[2]])
res2 = set()
for i in tmp2:
    res2.add(i[0])
cnt = 1
ans = 1000000
for i in tmp1:
    if i[0] == 'lzr010506':
        ans = min(ans, cnt)
        break
    if i[0] in res2:
        continue

    cnt += 1
cnt = 1
res1 = set()
for i in tmp1:
    res1.add(i[0])
for i in tmp2:
    if i[0] == 'lzr010506':
        ans = min(ans, cnt)
        break
    if i[0] in res1:
        continue

    cnt += 1
print(ans)

I

题目大意

在大小为 n ∗ m n*m nm的空间内存在镜子,需求得每次询问光线经过的镜子总数

题解

由于光线的反射性,故不存在某块镜子有两条同样的路径,故最后光线的路径必然是一个环或者一条链,对其进行判断,得到答案即可。

代码
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
const int N=1e3+5;

int ans[100005], anstype[100005];

int val[N][N][4];
int mp[N][N], vis[N][N][4], cir[N][N][4];
int to[4][4]={0, 1, 3, 2, 1, 0, 2, 3, 3, 2, 1, 0, 2, 3, 0, 1};
int tx[4]={-1, 1, 0, 0};
int ty[4]={0, 0, -1, 1};
int n, m, q, sx, sy;
int dfs(int x, int y, int d, int cnt){  
  if(x<1 || x>n || y<1 || y>m){
    //cout<<x<<" "<<y<<"\n";
    return 0;
  }
  if(vis[x][y][d]){
    cir[x][y][d]=1;
    return cnt;
  }
  if(cir[x][y][d]){
    return val[x][y][d];
  }
  int tmpd=to[mp[x][y]][d];
  int flag=1;
  for(int i=0; i<4; ++i){
    if(vis[x][y][i]){
      flag=0;
      break;
    }
  }
  if(flag && tmpd!=d){
    flag=1;
  }else{
    flag=0;
  }
  if(tmpd!=d) vis[x][y][d]=1;
  //cout<<"test: "<<x<<" "<<y<<" "<<mp[x][y]<<" "<<d<<" "<<tmpd<<" "<<cnt<<"\n";
  int dx=x+tx[tmpd], dy=y+ty[tmpd], tmp=dfs(dx, dy, tmpd, cnt+flag);
  if(tmpd!=d) vis[x][y][d]=0;
  if(cir[dx][dy][tmpd]){
    val[x][y][d]=tmp;
    cir[x][y][d]=1;
  }
  else val[x][y][d]=tmp+flag;
  return val[x][y][d];
}
int main(){
  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
  //ifstream infile("E:\\Contest\\nc\\27.in", ios::in);
  cin>>n>>m;
  for(int i=1; i<=n; ++i){
    for(int j=1; j<=m; ++j){
      char c;
      cin>>c;
      if(c=='|'){
        mp[i][j]=0;
      }else if(c=='-'){
        mp[i][j]=1;
      }else if(c=='/'){
        mp[i][j]=2;
      }else{
        mp[i][j]=3;
      }
      for(int k=0; k<4; ++k){
        val[i][j][k]=-1;
      }
    }
  }
  cin>>q;
  for(int i=1; i<=q; ++i){
    int d;
    string dir;
    cin>>sx>>sy>>dir;
    if(dir[0]=='a'){
      d=0;
    }else if(dir[0]=='b'){
      d=1;
    }else if(dir[0]=='l'){
      d=2;
    }else{
      d=3;
    }
    // ans[i]=dfs(sx+tx[d], sy+ty[d], d, 0);
    // anstype[i]=cir[sx+tx[d]][sy+ty[d]][d];
    cout<<dfs(sx+tx[d], sy+ty[d], d, 0)<<"\n";
  }
  // infile.close();
  // ifstream ansfile("E:\\Contest\\nc\\27.out", ios::in);
  // for(int i=1, realans; i<=q; ++i){
  //   ansfile>>realans;
  //   if(realans!=ans[i]){
  //     cout<<"Real: "<<realans<<" WA: "<<ans[i]<<" type: "<<anstype[i]<<"\n";
  //   }
  // }
  // ansfile.close();
  return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值