牛客小白月赛67 A-F 补题

牛客小白月赛67 A-F 补题

A 画牌河 签到

void Showball(){
   int n;
   cin>>n;
   for(int i=0;i<3;i++){
    for(int j=0;j<6;j++){
      if(n>0) cout<<1;
      else cout<<0;
      n--;
    }
    cout<<endl;
   }
}

B&D 不点两面 模拟
B题是D题的简单版本,赛时直接按照D的数据范围写的。
题意:给你1-m之间的数,有两种操作,第一种操作,给定一个x,
标记x-3和x+3。第二个操作,给定一个x,去除x。每次操作完都需要输出1-m中被标记数的个数。
思路:我们用一个桶去统计每个数被标记的次数,并且将标记的数维护在一个set中,去除操作时,我们只需要将次数减一即可。次数减为0的时候,我们把该数从set中删去即可。

void Showball(){
  int m,q;
  cin>>m>>q;
  set<int> s;
  map<int,int> mp;
  auto in = [&](int x) {return 1<=x&&x<=m;};
  while(q--){
    int op,num;
    cin>>op>>num;
    if(op==1){
        if(in(num-3)) mp[num-3]++,s.insert(num-3); 
        if(in(num+3)) mp[num+3]++,s.insert(num+3); 
    }else{
        if(in(num-3)) if(!--mp[num-3]) s.erase(num-3); 
        if(in(num+3)) if(!--mp[num+3]) s.erase(num+3); 
    }
    cout<<s.size()<<endl;
  }
}

C 一刀二分三角 数学+枚举
题意:给你三个点分别是(0,0),(xb,0),(xc,yc)构成的三角形,并且 x b > x c xb>xc xb>xc。让你去判断有没有可能从x=x0处分割这个三角形使得平分三角形的面积。
思路:数据范围比较小,我们可以直接枚举即可。分为0-xc,xc+1-xb这两个部分。面积公式就是初中数学知识。这里为了防止精度问题,在判断时,全部转化为除法来进行。

void Showball(){
   LL xb,xc,yc;
   cin>>xb>>xc>>yc;
   LL s=xb*yc,d=xb-xc;
   bool flg=false;
   for(int i=0;i<=xc;i++){
     if(2*yc*i*i==s*xc) {flg=true;break;}
   }
   for(int i=xc+1;i<=xb;i++){
    if(2*(s*(xb-i)-yc*i*(xb-i))==s*d) {flg=true;break;}
   }
   if(flg) cout<<"YES"<<endl;
   else cout<<"NO"<<endl;
}

E 游戏的买 期望dp
题意:小明想要买一款游戏,每天的价格有两个可能的值 a i a_i ai b i b_i bi,概率均为0.5。求出小明保证能买到该游戏的前提下,期望会花多少钱。
思路:期望dp,我们倒着进行考虑。
状态表示: d p [ i ] dp[i] dp[i]表示前i-1天都不买考虑i-n天的情况,期望的最低购买价格。
在第 i i i天有0.5概率价格为 a i a_i ai,还需要比较dp[i+1],选更小的情况。 b i b_i bi的情况同理。
转移方程:
d p [ i ] = 0.5 ∗ m i n ( a [ i ] , d p [ i + 1 ] ) + 0.5 ∗ m i n ( b [ i ] , d p [ i + 1 ] ) dp[i]=0.5∗min(a[i],dp[i+1])+0.5∗min(b[i],dp[i+1]) dp[i]=0.5min(a[i],dp[i+1])+0.5min(b[i],dp[i+1])

void Showball(){
  int n;
  cin>>n;
  vector<double> a(n+1),b(n+1),dp(n+2);
  for(int i=1;i<=n;i++) cin>>a[i];
  for(int i=1;i<=n;i++) cin>>b[i];
  dp[n+1]=inf;
  for(int i=n;i>=1;i--){
    dp[i]=0.5*min(dp[i+1],a[i])+0.5*min(dp[i+1],b[i]);
  }
  cout<<fixed<<setprecision(6)<<dp[1]<<endl;
}

F 翼伯父作威
题意:给你一个坐标(x,y)。两人轮流进行游戏,每次每个人可以向左(x-k,y),向下(x,y-k),向左下(x-k,y-k)。谁先走到(0,0)谁就赢得了游戏,设一共进行了c回合游戏。每人初始有1e9元,输家需要给赢家1e9-c元。计算赢家最多可以有多少元?
思路:经过一些手算研究,我们可以得到一些必败态,比如(1,2),(3,5),(4,7)…我们发现坐标之差的绝对值值逐渐递增的。并且横坐标是之前的数中没有出现的最小的数。很明显符合威佐夫博弈的性质。每个必败点我们用 a b s ( x − y ) abs(x-y) abs(xy)来标号。
我们可以预先处理出所有的必败点。
对于(x,y)是必败点。那么它最多能走 2 ∗ a b s ( x − y ) 2*abs(x-y) 2abs(xy)步。可以画图分析一下。
对于(x,y)不是必败点。那么我们就需要从三个方向去寻找有无必败点,然后走到必败点。因为我们需要赚更多的前,就需要越早结束游戏越好。那么我们就需要到最小的必败点。
具体处理是学习大佬的代码。非常简洁。

vector<int> vis(2*N+1);
void init(){
  int cnt=1;
  vis[0]=0;
  for(int i=1;i<=N;i++){
    if(!vis[i]){
        vis[i+cnt]=i;
        vis[i]=i+cnt;
        cnt++;
    }
  }
}
void Showball(){
   int x,y;
   cin>>x>>y;
   int c=2*abs(x-y)+1;
   if(x==vis[y]||y==vis[x]) c=min(c,2*abs(x-y));
   if(y>vis[x]) c=min(c,2*abs(x-vis[x])+1);
   if(x>vis[y]) c=min(c,2*abs(vis[y]-y)+1);
   cout<<inf-c<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Showball.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值