【NOIP】提高组2012 国王游戏

【算法】贪心+高精度

【题解】学自:http://blog.csdn.net/greatwjj/article/details/12129439

相邻两个人的顺序对前面的人和后面的人的钱都没影响。

令两个人分别为i和i+1,左手数字为a[i],a[i+1],右手数字为b[i],b[i+1],钱为w[i],w[i+1]。

令sum[i]为1...n的左手数字的总乘积。

w[i]=sum[i-1]/b[i]

w[i+1]=sum[i]/b[i+1]

因为sum[i]=sum[i-1]*a[i]

所以w[i+1]=sum[i-1]*a[i]/b[i+1]=w[i]*a[i]*b[i]/b[i+1]

由此可知w[i+1]的大小只与a[i],b[i],a[i]*b[i](即w[i])有关。

所以按a[i]*b[i]从小到大排序即可。

答案最大可以达到10000^1000即10^4000,要用高精度(T_T)

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1010,maxlen=5000;
struct cyc{int a,b,c;}a[maxn];
int n,lens,x,lmax,lena;
int sum[maxlen],ans[maxlen],maxs[maxlen];
bool cmp(cyc a,cyc b)
{return a.c<b.c;}
void cheng(int numi)
{
    int num=a[numi].a;x=0;
    for(int i=1;i<=lens;i++)
     {
         x+=sum[i]*num;
         sum[i]=x%10;
         x/=10;
     }
    while(x>0)sum[++lens]=x%10,x/=10;
//    printf("1...%d * lens=%d\n",numi,lens);
//    for(int i=1;i<=lens;i++)printf("%d",sum[i]);printf("\n");
}
void divs(int numi)
{
    int num=a[numi].b;x=0;
    for(int i=lens;i>=1;i--)
     {
         x=x*10+sum[i];
         ans[i]=x/num;
         x%=num;
     }
    lena=lens;
    while(ans[lena]==0&&lena>1)lena--;
//    printf("1...%d-1/%d / lens=%d\n",numi,numi,lena);
//    for(int i=1;i<=lena;i++)printf("%d",ans[i]);printf("\n");
    bool f=1;
    if(lena>lmax)f=0;else if(lena<lmax)f=1;else
     for(int i=lena;i>=1;i--)
      if(ans[i]>maxs[i]){f=0;break;}else if(ans[i]<maxs[i]){f=1;break;}
    if(!f)
     {
         for(int i=1;i<=lena;i++)maxs[i]=ans[i];
         lmax=lena;
     }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n+1;i++)scanf("%d%d",&a[i].a,&a[i].b),a[i].c=a[i].a*a[i].b;
    sort(a+2,a+n+2,cmp);//for(int i=1;i<=n+1;i++)printf("%d %d\n",a[i].a,a[i].b);
    sum[(lens=1)]=1;cheng(1);maxs[(lmax=1)]=0;
    for(int i=2;i<=n+1;i++)divs(i),cheng(i);
    for(int i=lmax;i>=1;i--)printf("%d",maxs[i]);
    return 0;
}

时间: 2024-10-03 07:51:44

【NOIP】提高组2012 国王游戏的相关文章

洛谷P1080 [NOIP2012提高组D1T2]国王游戏 [2017年5月计划 清北学堂51精英班Day1]

P1080 国王游戏 题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍的最前面.排好队后,所有的大臣都会获得国王奖赏的若干金币,每 位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右 手上的数,然后向下取整得到的结果. 国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序, 使得获得奖赏最多的大

noip提高组2011 Mayan游戏

Mayan游戏 描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.**游戏通关是指在规定的步数内消除所有的方块,**消除方块的规则如下: 1.每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将交换位置(参见图6到图7):如果目标位置上没有方块,那么被拖动的方块将从原来的竖列中抽出,并从

【NOIP2012提高组】国王游戏 贪心 + 高精度

题目分析 题目答案不具有单调性,所以不可以二分,转而思考贪心.因为无法确定位置,所以考虑如何才能让对于每一个$1 ~ i$使得$i$的答案最大,即$1 ~ i$最后一个最优.若设对于位置$i$,$a[i]$表示左手,$b[i]$表示右手,$S$为其前面所有人的左手之积,那么他的答案就是$\frac{S}{b[i]}$,如果存在在$i$后边的$j$的答案更优, 即$\frac{S * a[i]}{b[j]} > \frac{S * a[j]}{b[i]} => a[i] * b[i] >

noip提高组2012 借教室(luogu 1083)

原题链接:https://www.luogu.org/problem/show?pid=1083 坐在我对面的dalao瞬间就写出了线段树的解法,蒟蒻线段树太弱,只能写前缀和. 大致分析了一下,二分答案每天能否能满足当天的需求,能就向后找,不能就向前找, 找到最后都能满足,那就是能满足了,不然,此时就会停留在第一个不能满足的时刻. (终于会用插入代码的操作了(我太弱了...)) #include<cstdio> #include<cstring> using namespace s

NOIP提高组 1999 &amp; 2000 题解合集

[序言]话说我在学神奇算法的时候,基础应该也要巩固,于是打算提前把NOIP提高组的刷完. 具体的题目描述和提交我就在VIJOS上完成. [1999.1] 描述 给定一个信封,最多只允许粘贴N张邮票,计算在给定M(N+M<=10)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大max ,使得1-max之间的每一个邮资值都能得到. 例如,N=3,M=2,如果面值分别为1分.4分,则在l分-6分之间的每一个邮资值都能得到(当然还有8分.9分和12分):如果面值分别为1分.3分

Vijos P1002 过河 (NOIP提高组2005)

链接:https://www.vijos.org/p/1002 解析: 若 p*x+(p+1)*y=Q(采用跳跃距离p和p+1时可以跳至任何位置Q),则在Q ≥ P*(P-1)时是一定有解的. 由于题目给出的一个区间是1≤S≤T≤10,于是当相邻的两个石子之间的距离不小于8*9=72时,则后面的距离都可以到达,我们就可以认为它们之间的距离就是72.如此一来,我们就将原题L的范围缩小为了100*72=7200,动态规划算法完全可以承受了. 但是当S=T时,上述等式是无法使用的,在这种情况下,只需要

NOIP提高组2004 合并果子题解

NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了.多多在合并果子时总共消耗的体力等于每次合并所耗体力之和. 因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力.假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出

NOIP 提高组2013 火柴排队 (Vijos P1842)

描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑ i=1 n (a i ?b i ) 2  ,其中 a i   表示第一列火柴中第 i 个火柴的高度,b i   表示第二列火柴中第 i 个火柴的高度. 每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小.请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模

2017.11.25【NOIP提高组】模拟赛A组

2017.11.25[NOIP提高组]模拟赛A组 T1 3467. [NOIP2013模拟联考7]最长上升子序列(lis) T2 3468. [NOIP2013模拟联考7]OSU!(osu) T3 3472. [NOIP2013模拟联考8]匹配(match) T1 有转移方程f[i]=max{f[j]}+1,a[j]<a[i] 可以用线段树+离散化维护这个方程,因为涉及以往状态可以用主席树维护 打太丑爆空间了 Code 1 #include<cstdio> 2 #include<c