[NOIP2017模拟]Ball
来源:互联网 发布:拉比 婴儿床 知乎 编辑:程序博客网 时间:2024/05/17 01:51
题目背景
SOURCE:NOIP2015-SHY-9
题目描述
Alice 与 Bob 在玩游戏。他们一共玩了 t 轮游戏。游戏中,他们分别获得了 n 个和 m 个小球。每个球上有一个分数。每个人的得分都为他所获得所有小球分数的乘积,分数小者获胜。问每轮游戏谁会获胜?请输出每轮游戏的胜者。数据保证不会出现平局,且两个人分数差异大于任意一个人分数的 1% 。
输入格式
第一行为两人玩的轮数 t(1≤t≤10)。
每一轮游戏的输入中:
第一行一个整数 n,代表 Alice 获得球的个数。
第二行为 n 个整数
第三行一个整数 m,代表 Bob 获得球的个数。
第四行为 m 个整数
输出格式
输出共 t 行,每行为该轮胜者的名字“Alice”或“Bob”。
样例数据
输入
1
3
2 3 4
4
1 3 4 5
输出
Alice
备注
【样例说明】
Alice:2 * 3 * 4 = 24
Bob: 1 * 3 * 4 * 5 = 60
【数据范围】
对于 40% 的数据:n,m,
对于 100% 的数据:1≤n,m≤100000;-10000≤
分析:如果说连乘的话肯定超long long,有没有办法把它变小,最好把它变成加法呢?有,用对数!这样只需要把读入的数取对数再加起来,连int都不会超!!!但是,要注意判负数和0。
还有一种算法,就是取一个极大值为基数,连乘到大于它就又新开一个数组重新开始乘,最后比较哪个开的数组多哪个就更大(当然要判负数和0),如果一样那就一一对应相除得到一堆分数再相乘,最后得到的数小于1就是Alice赢,反之Bob赢。
代码
解法一
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>#include<queue>#include<set>using namespace std;int getint(){ int sum=0,f=1; char ch; for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar()); if(ch=='-') { f=-1; ch=getchar(); } for(;isdigit(ch);ch=getchar()) sum=(sum<<3)+(sum<<1)+ch-48; return sum*f;}const int maxn=100010;int T,n,m,bj10,bj1,bj20,bj2;//bj1、bj2判断正负,bj10、bj20判断是否有0int a1,a2;double ans1,ans2;int main(){ freopen("ball.in","r",stdin); freopen("ball.out","w",stdout); T=getint(); while(T--) { bj1=bj2=bj10=bj20=0; ans1=0,ans2=0; n=getint(); for(int i=1;i<=n;++i) { a1=getint(); if(a1<0) { bj1^=1; ans1+=log10(-a1);//log(这个是e为底)、log2、log10都是C++自带的函数 } else if(a1==0) { bj10=1; continue;//千万不要学我在这里自信满满地break掉,数据都还没读完啊...... } else ans1+=log10(a1); } m=getint(); for(int i=1;i<=m;++i) { a2=getint(); if(a2<0) { bj2^=1; ans2+=log10(-a2); } else if(a2==0) { bj20=1; continue; } else ans2+=log10(a2); } if(bj10!=1&&bj20!=1)//两个都不为0 { if((bj1==1&&bj2==0)||(bj1==1&&bj2==1&&ans1>ans2)||(bj1==0&&bj2==0&&ans1<ans2))//Alice负Bob正、Alice负得更厉害、Bob正得更厉害都是Alice赢 cout<<"Alice"<<'\n'; else if((bj1==0&&bj2==1)||(bj1==1&&bj2==1&&ans1<ans2)||(bj1==0&&bj2==0&&ans1>ans2)) cout<<"Bob"<<'\n'; } else if(bj10==1) { if(bj2==1) cout<<"Bob"<<'\n'; else cout<<"Alice"<<'\n'; } else if(bj20==1) { if(bj1==1) cout<<"Alice"<<'\n'; else cout<<"Bob"<<'\n'; } } return 0;}
解法二
#include<iostream>#include<cstring>#include<string>#include<cstdlib>#include<cstdio>#include<ctime>#include<cmath>#include<cctype>#include<iomanip>#include<algorithm>using namespace std;const int N=1e5+10;const long long INF=1e16;int check1,check2,t,n,m,check,tot1,tot2;double sh[N],ans;long long sum1[N],sum2[N],a[N],b[N];bool flag1,flag2;int readint(){ char ch;int i=0,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') {ch=getchar();f=-1;} for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0'; return i*f;}int main(){ //freopen("ball.in","r",stdin); //freopen("ball.out","w",stdout); t=readint(); while(t--) { check1=0;check2=0;check=0;tot1=1;tot2=1;flag1=false;flag2=false; ans=1; n=readint(); for(int i=1;i<=n;i++) { a[i]=readint(); if(a[i]<0) { check1=check1^1; a[i]=abs(a[i]); } if(a[i]==0) flag1=true; } m=readint(); for(int i=1;i<=m;i++) { b[i]=readint(); if(b[i]<0) { check2=check2^1; b[i]=abs(b[i]); } if(b[i]==0) flag2=true; } if(flag1==false&&flag2==false) { if(check1==1&&check2==0) {printf("Alice\n");continue;} if(check1==0&&check2==1) {printf("Bob\n");continue;} } if(flag1==true&&flag2==false) { if(check2==1) {printf("Bob\n");continue;} else {printf("Alice\n");continue;} } if(flag1==false&&flag2==true) { if(check1==1) {printf("Alice\n");continue;} else {printf("Bob\n");continue;} } sum1[1]=1;sum2[1]=1; for(int i=1;i<=n;i++) { sum1[tot1]*=a[i]; if(sum1[tot1]>INF) {tot1++;sum1[tot1]=1;}//不断连乘和开新数组 } for(int i=1;i<=m;i++) { sum2[tot2]*=b[i]; if(sum2[tot2]>INF) {tot2++;sum2[tot2]=1;} long long x=sum2[46]; } if(tot1>tot2) check=1; if(tot1<tot2) check=2; if(tot1==tot2) { if(tot1==1) { if(sum1[1]<sum2[1]) check=2; else check=1; } else { for(int i=1;i<=tot1;i++) sh[i]=(sum1[i]*1.0)/sum2[i];//对应相除得到分数 for(int i=1;i<=tot1;i++) ans*=sh[i];//然后乘起来 if(ans<1) check=2; else check=1; } } if(check==2) { if(check1==0&&check2==0) {printf("Alice\n");continue;} if(check1==1&&check2==1) {printf("Bob\n");continue;} } else { if(check1==0&&check2==0) {printf("Bob\n");continue;} if(check1==1&&check2==1) {printf("Alice\n");continue;} } } return 0;}
本题结。
- [NOIP2017模拟]Ball
- HDU 4811 Ball 模拟
- [NOIP模拟] Ball
- NOIP2017模拟赛1
- NOIP2017模拟赛8
- NOIP2017模拟赛9
- [NOIP2017模拟]切蛋糕
- [NOIP2017模拟]随机图
- [NOIP2017模拟]能源
- [NOIP2017模拟]电影
- [NOIP2017模拟]鸭舌
- [NOIP2017模拟]permut
- [NOIP2017模拟]beautiful
- [NOIP2017模拟]路径
- [NOIP2017模拟]流
- [NOIP2017模拟]subset
- [NOIP2017模拟]hello
- [NOIP2017模拟]table
- POJ
- [HTML] H5移动端知识点总结
- GIT基本概念和用法总结
- LWC 53:693. Binary Number with Alternating Bits
- js正则入门
- [NOIP2017模拟]Ball
- ConfigReader(二)—— MapLoadConfig
- 自用git指令笔记
- linux安装svn服务器(yum方式)
- 一起来学SQL(三)
- pandas使用入门
- Android群英传学习——控件架构与自定义控件
- php函数call_user_func和call_user_func_array详解
- 自己写“扫雷”(二).业务逻辑实现