【cf contest 1119 G】Get Ready for the Battle

题目

你有\(n\)个士兵,需要将他们分成\(m\)组,每组可以为0;

现在这些士兵要去攻打\(m\)个敌人,每个敌人的生命值为\(hp_i\) ;

一轮游戏中一组士兵选定一个攻打的敌人,敌人生命值-=这组的人数;

胜利的判定是所有敌人的生命值为非正的;

输出胜利的最小轮数,可以达到最小轮数的分配方式,并输出每轮的策略;

\(1 \le m \le n \le 10^6 \ , \ 1 \le \sum hp_i \le 10^6\) ;

题解

  • 答案的下界是\(\lceil \frac{\sum_{i=1}^{m} \ hp_i} n \rceil\) ,考虑构造这个下界;
  • 注意到所有的和为\(n\),首先让 ?$ hp_i $ 对 ?$ n $ 取模;

    只需要构造
    \[
    \begin{cases}
    s_i &= (\sum_{j=1}^{i} hp_j) \ mod \ n &i \lt m \s_i &= n &i = m \\end{cases}
    \]

  • 排序得到\(s_1,\cdots,s_{m-1},s_m\),构造\(s_i-s_{i-1}\)即可;
  • 容易知道只有最后一次的\(n\)没有被充分利用,所以满足下界;
  • 再 \(for\) 一遍模拟取模的过程求出策略即可;
    #include<bits/stdc++.h>
    #define mk make_pair
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    const int N=1000010;
    int n,m,a[N],pos[N],cnt;
    pair<int,int>b[N];
    vector<int>ans[N];
    char gc(){
      static char*p1,*p2,s[1000000];
      if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
      return(p1==p2)?EOF:*p1++;
    }
    int rd(){
      int x=0;char c=gc();
      while(c<'0'||c>'9')c=gc();
      while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
      return x;
    }
    char ps[1000000],*pp=ps;
    void flush(){
      fwrite(ps,1,pp-ps,stdout);
      pp=ps;
    }
    void push(char x){
      if(pp==ps+1000000)flush();
      *pp++=x;
    }
    void write(int x){
      static int sta[20],top;
      if(!x){push('0');return;}
      while(x)sta[++top]=x%10,x/=10;
      while(top)push(sta[top--]^'0');
    }
    int main(){
    //    freopen("G.in","r",stdin);
    //    freopen("G.out","w",stdout);
      n=rd();m=rd();
      for(int i=1;i<=m;++i){
          a[i]=rd();
          int tmp=a[i]/n;
          for(int k=1;k<=tmp;++k)
          for(int j=1;j<=m;++j)ans[j].pb(i);
          a[i]%=n;
      }
      for(int i=1,now=0;i<=m;++i){
          now+=a[i];
          if(now>=n)now-=n;
          if(i!=m)b[i]=mk(now,i);
      }
      sort(b+1,b+m);
      b[m]=mk(n,m);
      b[0]=mk(0,0);
      for(int i=1;i<=m;++i)pos[b[i].se]=i;
      for(int i=1,lst=1,now=0;i<=m;++i){
          now+=a[i];
          if(now>=n){
              for(;lst<=m;++lst)ans[lst].pb(i);
              lst=0;now-=n;
          }
          if(!now)continue;
          for(;lst<=pos[i];++lst)ans[lst].pb(i);
      }
      cnt=ans[1].size();
      write(cnt),push('\n');
      for(int i=1;i<=m;++i)write(b[i].fi-b[i-1].fi),push(' ');
      push('\n');
      for(int i=0;i<cnt;++i){
          for(int j=1;j<=m;++j)write(ans[j][i]),push(' ');
          push('\n');
      }
      flush();
      return 0;
    }

原文地址:https://www.cnblogs.com/Paul-Guderian/p/10804245.html

时间: 2024-10-30 20:53:04

【cf contest 1119 G】Get Ready for the Battle的相关文章

【CF 549G Happy Line】排序

题目链接:http://codeforces.com/problemset/problem/549/G 题意:给定一个n个元素的整数序列a[], 任意时刻对于任一对相邻元素a[i-1]. a[i],若a[i-1] < a[i] 则要依次执行如下两个操作: 1. a[i-1]--, a[i]++: 2. 交换a[i-1]和a[i]的位置. 经过若干次1.2操作后,若能使整个序列变成非降的,则输出最终的序列:否则输出":(". 数据范围:n 属于 [1, 2*10^5], a[i]

【CF global1 D / CF1110D】 Jongmah

题意 你有n个数字,范围[1, m],你可以选择其中的三个数字构成一个三元组,但是这三个数字必须是连续的或者相同的,每个数字只能用一次,问这n个数字最多构成多少个三元组? 分析 这里想谈一下DP的一个套路,捆绑 有的DP题目,它可能会要求和一些东西捆绑,求方案数,这种时候如何单点设置状态呢? 以这个题为例,只考虑前i种数字,对于数字i,它可能 (i,i,i) (i-2,i-1,i) (i-1,i) (i,) 如果是后两种,它还未构成一个合法的序列,我们还不知道是否存在i+1来完善它 也就是考虑前

【CF刷题】14-05-12

Round 236 div.1 A:只需要每个点连接所有比他大的点,知道边用完为止. //By BLADEVIL #include <cmath> #include <cstdio> #define maxn 25; using namespace std; int main() { int task; scanf("%d",&task); while (task--) { int n,p; scanf("%d%d",&n,&

【CF 520D】Cubes

[CF 520D]Cubes 怎么说呢--英语阅读题+超级大模拟-- 最重要的是知道怎么出来的数据...题意好懂 xy坐标内给出几个单位正方形 以正方形左下点坐标给出 y=0为地面 正方形下面或者左右下方至少存在一个正方形他才能稳定.. 正方形按0~m-1标号 每次只能取出不影响整体结构的正方形 甲乙玩一个游戏 交替取正方形 每取下一个按从左到右的顺序排好 得到一个大数 重点来了! 取出的数是m进制 转换为十进制是最终结果 甲希望结果最大 乙希望结果最小 问结果为多少 甲先取 题意明白了模拟就行

【机器学习算法-python实现】协同过滤(cf)的三种方法实现

(转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景 协同过滤(collaborative filtering)是推荐系统常用的一种方法.cf的主要思想就是找出物品相似度高的归为一类进行推荐.cf又分为icf和ucf.icf指的是item collaborative filtering,是将商品进行分析推荐.同理ucf的u指的是user,他是找出知趣相似的人,进行推荐.通常来讲icf的准确率可能会高一些,通过这次参加天猫大数据比赛,我觉得只有在数据量非

【G】开源的分布式部署解决方案(二) - 好项目是从烂项目基础上重构出来的

G.系列导航 [G]开源的分布式部署解决方案 - 预告篇 [G]开源的分布式部署解决方案(一) - 开篇 [G]开源的分布式部署解决方案(二) - 好项目是从烂项目基础上重构出来的 分析目前项目结构 眼前出现这么一坨坨的文件夹,相信很多人已经看不下去了.是的,首先就是要把它给做掉. 按照这个项目文件夹的命名意图,大概可以划分如下: 1.Business:业务代码 2.Data:数据访问 3.Helpers:辅助类(通用类库之类的) 4.Models:各种模型(包括视图模型) 5.theme:皮肤

【线段树】【树状数组】【CF 121E】幸运数列

1922. [CF 121E]幸运数列 ★★★ 输入文件:cf121e.in 输出文件:cf121e.out 简单对比 时间限制:3 s 内存限制:256 MB [题目描述] 对于欧洲人来说,"幸运数"是指那些十进制只由4或7组成的数.财务员Petya需要维护一个支持如下操作的整数数列: add l r d - 表示将[l, r]区间内的所有数加上一个正整数d(). count l r - 统计[l, r]区间内有多少个"幸运数".() 请你帮助Petya实现它.

【G】开源的分布式部署解决方案(三) - 一期规划定稿与初步剖析

G.系列导航 [G]开源的分布式部署解决方案 - 预告篇 [G]开源的分布式部署解决方案(一) - 开篇 [G]开源的分布式部署解决方案(二) - 好项目是从烂项目基础上重构出来的 [G]开源的分布式部署解决方案(三) - 一期规划定稿与初步剖析 抱歉 首先我先说声抱歉,因为上一篇结尾预告第三篇本该是“部署项目管理”,那为什么变成本篇呢? 请容我解释一下,在预告篇到现在为止,经常会有人问我这个项目到底是干什么的.或许之前写的比较粗糙.那我相信目前定稿后的功能概览图应该会给大家一个比较清晰的认识.

【CF 474E】Pillars

[CF 474E]Pillars 离散化+线段树dp 大半夜写出来了...好长好长好长好长好挫--先把高度排序离散化 我又开了个哈希数组用来查某点对应离散后的点 然后遍历每个点时二分出满足题意的区间(1~h-d)(h+d~max) 然后线段树查两个区间当前最大长度的序列 累计到当前点对应的树内点 同时更新他的父亲点们的最大长度 再把之前最大长度的末尾作为当前点的前驱 如果没有就用当前点自己做前驱 最后输出树根存的节点的前驱们(即为树内最长的序列) 各种节点哈希的有点混乱--代码--看乱了就别看了