列表

详情


NC53273. 馕

描述

题目译自 JOISC 2019 Day1 T3「ナン / Naan
JOI咖喱店以提供很长(?)的馕而闻名。它提供的馕有L种口味,编号从1到L。「JOI特色馕」是店内最受欢迎的一道菜。馕的总长度为L厘米。我们定义「点X」为馕上距离馕左端X厘米处的点。对于,点j-1和点j间的一段馕是第j种口味的。
有N个人来到了JOI咖喱店,他们每个人的偏好都不同,具体的说,第i个人每吃一厘米的风味j的馕,就会获得的快乐度。
他们只买了一个JOI特色馕,他们将用下面的方式分享馕:
  1. 选择N-1个分数,满足
  2. 选择N的一个排列
  3. 对于每一个,在点X_k的位置切一刀,然后馕将被切成N个部分
  4. 个部分的左端点为,右端点为,这里我们认为
  5. P_i个人将吃掉第i个部分。
现在他们想公平的分配馕,他们认为一种分配方法是公平的,当且仅当每个人获得的快乐度都不小于他们独吞整个馕所获得的快乐度的
现在给你N个人的信息,你需要判断是否存在一种公平的分配方式,如果存在,输出一组分配方案。

输入描述

从标准输入中读取数据。
第一行两个整数N,L。
接下来N行,每行L个整数,第i行第j个数为

输出描述

输出数据到标准输出中。
如果无解,输出一行-1;
如果有解,首先输出N-1行,第i行两个整数A_i,B_i,要求A_i,B_i是一对满足的整数对。
接下来一行N个整数,第i个数表示P_i
你的输出需要满足:
P_1,...,P_N是一个1,...,N的排列。第i个人获得的总快乐度不小于
A_i,B_i不必互质。
可以证明,如果输入数据有解,那么一定存在一组满足上述条件的解。

示例1

输入:

2 5
2 7 1 8 2
3 1 4 1 5

输出:

14 5
2 1

说明:

在这组样例中,第一个人如果吃掉整个馕,会得到2+7+1+8+2=20的快乐度,第二个人如果吃掉整个馕,会获得3+1+4+1+5=14的快乐度。因此,如果第一个人获得不小于\frac{20}{2}=10的快乐度,且第二个人获得不小于\frac{14}{2}=7的快乐度,就是一组合法的解。
如果在点\frac{14}{5}的位置切一刀,第一个人会获得1 \times \frac{1}{5}+8+2= \frac{51}{5}的快乐度,第二个人会获得3+1+4 \times \frac{4}{5}= \frac{36}{5}的快乐度。因此这是一组合法的解。

示例2

输入:

7 1
1
2
3
4
5
6
7

输出:

1 7
2 7
3 7
4 7
5 7
6 7
3 1 4 2 7 6 5

说明:

在这组样例中,馕只有一种风味。只要把馕七等分,就是合法的方案,与P_1,...,P_N无关。

示例3

输入:

5 3
2 3 1
1 1 1
2 2 1
1 2 2
1 2 1

输出:

15 28
35 28
50 28
70 28
3 1 5 2 4

说明:

注意A_i,B_i(1 \le i \le N)不必互质。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1607ms, 内存消耗: 64360K, 提交时间: 2020-04-19 14:49:08

#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;const int Q=1<<11;struct dt{ll u,w;dt(){}dt(ll a,ll b){u=a,w=b;}void P(){printf("%lld %lld\n",u,w);}}s[Q][Q];bool operator<(dt a,dt b){return (long double)a.u*b.w<(long double)b.u*a.w;}ll f[Q];int b[Q],o[Q];int main(){int n,l;scanf("%d%d",&n,&l);for(int p=1;p<=n;p++){for(int i=1;i<=l;i++)scanf("%lld",&f[i]),f[i]+=f[i-1];for(int h=0,i=1;i<=n;i++){while(f[h+1]*n<f[l]*i)++h;ll p2=1LL*n*(f[h+1]-f[h]),p1=1LL*h*p2+f[l]*i-f[h]*n,g=__gcd(p1,p2);s[p][i]=dt(p1/g,p2/g);}}for(int i=1;i<=n;i++){int x=0;for(int j=1;j<=n;j++)if((!o[j])&&((!x)||s[j][i]<s[x][i]))x=j;o[x]=1;b[i]=x;}for(int i=1;i<n;i++)s[b[i]][i].P();for(int i=1;i<=n;i++)printf("%d ",b[i]);}

上一题