2 条题解
-
2
国王游戏 题解
分析
根据题意我们可以知道,大臣1和大臣2位置能交换的必要条件是: 大臣2放在大臣1的前面得到的最大值更加小。 那么我们分别讨论两种情况下的最大值,假设只有两个大臣: 如果大臣1放在前面,他俩获得的金币数分别为: a0 / b1 , a0 * a1 / b2 如果大臣2放在前面,他俩获得的金币数分别为: a0 / b2 , a0 * a2 / b1 首先,我们约去式子里面的a0,然后分别讨论两种情况的最大值,就变成了比较: max(1/b1,a1/b2)和max(1/b2,a2/b1)的大小 根据0<a,a是整数的条件,我们可以得出: a1/b2 >= 1/b2、1/b1 <= a2/b1
那么,如果1/b1是最大的,则有 1/b1>=a2/b1,只可能左右两边相等,则有1/b2<=a2/b1,所以两种情况的最大值是一样的,则不用交换。 同理可得1/b2是最大的情况也不用交换。 那么我们就只要a1/b2和a2/b1的大小就可以了,也就是说如果a1/b2>a2/b1,那么就要交换,变形得: a1 * b1 > a2 * b2 表示要交换,我们排序就只要按照a*b的从小到大排就可以了。
记得用高精
高精度我就不讲了.....太简单 如果不会,见:https://www.luogu.com.cn/problem/solution/P1601
作为出题人肯定要粘上代码!!! look!!!
#include<bits/stdc++.h> using namespace std; struct node{ int a,b; char cnta[10000],all[10000];//cnta 为前面所有a的乘积的逆序 all为乘积正序 char ca[100];//a转化为字符数组 char ans[10000];//所获得金币数 int lans; }da[1001]; bool cmp(node a,node b){ return a.a*a.b<b.a*b.b; } bool cmp2(node a,node b){//高精度比较 if(a.lans!=b.lans) return a.lans>b.lans; else{ int i; for(i=0;i<a.lans;i++) if(a.ans[i]==b.ans[i]) { continue; } else return a.ans[i]>b.ans[i]; } return 1==1; } void doit(int a,char b[]){//将数值转化成字符数组 int lb=0; while(a>0){ b[lb++]=a%10+'0'; a/=10; } b[lb]='\0'; } void add(char c[],char d[],int i){//错位相加 int lc=strlen(c),j; int jw = 0,tmp; for(j=0;j<lc;j++,i++){ tmp=(d[i]>0?d[i]-'0':0)+c[j]-'0'+jw; d[i]=tmp%10+'0'; jw=tmp/10; } if(jw){ d[i++]=jw+'0'; } d[i]='\0'; } void gc(char a[],char b[],char d[]){//高乘 int la=strlen(a); int lb=strlen(b); int i,j; char c[10000];//记录乘数的每一位乘以被乘数的积 for(i=0;i<la;i++){ int tmp; int jw = 0; int lc = 0; for(j=0;j<lb;j++){ tmp = (a[i]-'0') * (b[j]-'0') + jw; c[lc++] = tmp % 10 + '0'; jw = tmp / 10; } if(jw) c[lc++]=jw+'0'; c[lc]='\0'; add(c,d,i); } } void mult(char a[],int b, char c[]){ int i = 0 , tag = 0 , la = strlen(a) , lc = 0; int d = 0; while(i<=la){ if(b>d){ d=d*10+a[i++]-'0'; if(tag) c[lc++]='0'; }else{ c[lc++]=d/b+'0'; d=d%b; d=d*10+a[i++]-'0'; tag = 1; } } if(tag==0)c[lc++]='0'; c[lc]='\0'; } int main(){ int n,i,j; memset(da,0,sizeof(da)); scanf("%d",&n); scanf("%d%d",&da[0].a,&da[0].b); for(i=1;i<=n;i++){ scanf("%d%d",&da[i].a,&da[i].b); } sort(da+1,da+n+1,cmp); doit(da[0].a,da[0].ca); da[0].cnta[0]='1'; da[0].cnta[1]='\0'; for(i=1;i<=n;i++){//得到前面大臣左手金币数的乘积的逆序 doit(da[i].a,da[i].ca); gc(da[i-1].cnta,da[i-1].ca,da[i].cnta); } for(i=1;i<=n;i++){//将乘积逆转 int k=0; for(j=strlen(da[i].cnta)-1;j>=0;j--) da[i].all[k++]=da[i].cnta[j]; da[i].all[k]='\0'; } for(i=1;i<=n;i++){//得到每一位大臣能获得的金币数 mult(da[i].all,da[i].b,da[i].ans); da[i].lans = strlen(da[i].ans); } int ans = 1; for(i=2;i<=n;i++){ if(!cmp2(da[ans],da[i])) ans=i; } printf("%s\n",da[ans].ans); return 0; }
很简单
信息
- ID
- 481
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 8
- 已通过
- 6
- 上传者