CF1119G. Get Ready for the Battle

CF1119G. Get Ready for the Battle

题目描述

Solution

妙妙构造题。
考虑这样一个过程:所有人一起打第一个怪,每次打 n n n,最后剩下 k 1 < n k_1<n k1<n,就找一些加起来正好为 k 1 k_1 k1的组打掉 k 1 k_1 k1,剩下的 n − k 1 n-k_1 nk1打第二个怪,然后重复打 n n n,余数 k 2 k_2 k2找一些组正好打掉这样一个过程,直到剩下最后一个怪,打玩 n − k m − 1 n-k_{m-1} nkm1,再一直打 n n n到非正。

若能够构造 s 1.. m s_{1..m} s1..m,满足可以配成 k 1 . . . k m − 1 k_1...k_{m-1} k1...km1中的任意数。
即可求出答案为 ⌈ ∑ a i n ⌉ \lceil \frac{\sum a_i}{n} \rceil nai

于是我们将 k k k排序,令 s i = k i + 1 − k i s_i=k_{i+1}-k_{i} si=ki+1ki s m = n − k m − 1 s_m=n-k_{m-1} sm=nkm1,可以满足任意 k i k_i ki s s s前缀和中的一个。

构造完 s i s_i si之后,事实上只需要用 a 1 a_1 a1依次减 s [ 1... m ] s[1...m] s[1...m],减完 s [ m ] s[m] s[m]之后再从 s [ 1 ] s[1] s[1]开始减。若减的过程中 a 1 ≤ 0 a_1\leq 0 a10,则用 a 2 a_2 a2继续减,直到 a m ≤ 0 a_m\leq 0 am0

事实上这样做, a 1.. ( m − 1 ) a_{1..(m-1)} a1..(m1)都会减为0,达到最优解。
原因参照下例:
a 1 − n − n − . . . − n − k 1 = 0 a_1-n-n-...-n-k_1=0 a1nn...nk1=0
a 2 − ( n − k 1 ) % n − n − n − . . . − n − k 2 = 0 a_2-(n-k1)\%n-n-n-...-n-k_2=0 a2(nk1)%nnn...nk2=0
a 3 − ( n − k 2 ) % n − n − n − . . . − n − k 3 = 0 a_3-(n-k2)\%n-n-n-...-n-k_3=0 a3(nk2)%nnn...nk3=0
. . . . . . ...... ......
a m − ( n − k m − 1 ) % n − n − n − . . . − n ≤ 0 a_m-(n-k_{m-1})\%n-n-n-...-n\leq0 am(nkm1)%nnn...n0
k i k_i ki ( n − k i ) (n-k_i) (nki)配成一段连续的 s [ 1.. m ] s[1..m] s[1..m]

且不可能出现如下情况:
a 1 − n − n − . . . − n − k 1 = 0 a_1-n-n-...-n-k_1=0 a1nn...nk1=0
a 2 − k 2 = 0      ( a 2 < ( n − k 1 ) % n ) a_2-k_2=0\;\;(a_2<(n-k1)\%n) a2k2=0(a2<(nk1)%n)
. . . . . . ...... ......

因为 k 2 = ( a 1 + a 2 ) % n k_2=(a_1+a_2)\%n k2=(a1+a2)%n,因此 k 2 = ( k 1 + k 2 ) % n k_2=(k_1+k_2)\%n k2=(k1+k2)%n,则 k 1 % n = 0 k_1\%n=0 k1%n=0,则 k 1 = 0 k_1=0 k1=0

因此按此过程一定是按 s [ 1.. m ] s[1..m] s[1..m]连续减下去,减完 s [ m ] s[m] s[m],从 s [ 1 ] s[1] s[1]继续减下去。

Code(讲述凌乱,理解代码体验极佳)

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>

#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se second

using namespace std;

template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }

typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;

const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int MAXN=1000005;
const ll INF=1ll<<60;
/*--------------------------------------------------------------------*/
inline int read()
{
	int f=1,x=0; char c=getchar();
	while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }
	while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
	return x*f;
}
VI Ans;
int a[MAXN],b[MAXN],s[MAXN];
int main()
{
	int n=read(),m=read(),sum=0; 
	b[1]=n;
	for (int i=1;i<=m;i++) sum+=(a[i]=read()),b[i+1]=sum%n;
	sort(b+1,b+m+1);
	for (int i=1;i<=m;i++) s[i]=b[i]-b[i-1];
	for (int i=1,id=0;i<=m;i++)
	{
		int t=a[i];
		while (t>0) Ans.PB(i),t-=s[id%m+1],id++;
	}
	printf("%d\n",(sum-1)/n+1);
	while (Ans.size()%m) Ans.PB(1);
	for (int i=1;i<=m;i++) printf("%d%c",s[i]," \n"[i%m==0]);
	for (int i=0;i<Ans.size();i++) printf("%d%c",Ans[i]," \n"[(i+1)%m==0]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值