Processing math: 100%

[loj3032]馕

(直接贪心会导致分子和分母过大)

Si=Lj=1Vi,j(即其独吞整个馕的快乐度),对第i个人求出n个位置x1,x2,...,xn1,使得以此划分出的n段中,其吃每一段的快乐度都恰为Sin

假设j1<xij,那么(jxi)Vj=jk=1ViinS,即可得到xi的分子和分母的范围分别为2×1084×1011,都可以存储

xi=j+inSjk=1ViVj

接下来,对于答案的xi(从小到大枚举i),选择未选择的人中xi的最小值以及对应的人即可

关于这一做法的正确性,考虑这个人的xi1必然不小于答案的xi1(否则应该选其),即成立

(分数比较时,分子乘分母的范围为8×1019,可以使用__int128)

复制代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 2005
 4 #define ll long long
 5 #define LL __int128
 6 LL mul(ll x,ll y){
 7     return (LL)x*y;
 8 }
 9 struct Frac{
10     ll x,y;
11     bool operator < (const Frac &k)const{
12         return mul(x,k.y)<mul(y,k.x);
13     }
14     Frac operator + (const Frac &k)const{
15         return Frac{x*k.y+y*k.x,y*k.y};
16     }
17     Frac operator * (const Frac &k)const{
18         return Frac{x*k.x,y*k.y};
19     }
20 }x[N][N];
21 int n,m,a[N][N],sum[N][N],vis[N],ans[N];
22 int main(){
23     scanf("%d%d",&n,&m);
24     for(int i=1;i<=n;i++)
25         for(int j=1;j<=m;j++){
26             scanf("%d",&a[i][j]);
27             sum[i][j]=sum[i][j-1]+a[i][j];
28         }
29     for(int i=1;i<=n;i++)
30         for(int j=1,k=1;j<n;j++){
31             while (Frac{sum[i][k],1}<Frac{1LL*j*sum[i][m],n})k++;
32             x[i][j]=Frac{k,1}+(Frac{1LL*j*sum[i][m],n}+Frac{-sum[i][k],1})*Frac{1,a[i][k]};
33         }
34     for(int i=1;i<=n;i++){
35         int k=0;
36         for(int j=1;j<=n;j++)
37             if ((!vis[j])&&((!k)||(x[j][i]<x[k][i])))k=j;
38         vis[k]=1,ans[i]=k;
39         if (i<n)printf("%lld %lld\n",x[k][i].x,x[k][i].y);
40     }
41     for(int i=1;i<=n;i++)printf("%d ",ans[i]);
42 } 
View Code
复制代码

 

posted @   PYWBKTDA  阅读(39)  评论(0编辑  收藏  举报
编辑推荐:
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
阅读排行:
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 2025成都.NET开发者Connect圆满结束
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 用一种新的分类方法梳理设计模式的脉络
点击右上角即可分享
微信分享提示