[NOIP模拟] Ball

来源:互联网 发布:双色球万能矩阵必中6码 编辑:程序博客网 时间:2024/05/16 12:30

题目描述:
题目背景: SOURCE:NOIP2015-SHY-9
Alice 与 Bob 在玩游戏。他们一共玩了 t 轮游戏。游戏中,他们分别获得了 n 个和 m 个小球。每个球上有一个分数。每个人的得分都为他所获得所有小球分数的乘积,分数小者获胜。问每轮游戏谁会获胜?请输出每轮游戏的胜者。数据保证不会出现平局,且两个人分数差异大于任意一个人分数的 1% 。
输入格式:
第一行为两人玩的轮数 t(1≤t≤10)。
每一轮游戏的输入中:
第一行一个整数 n,代表 Alice 获得球的个数。
第二行为 n 个整数 ai,代表 Alice 每个球的分数。
第三行一个整数 m,代表 Bob 获得球的个数。
第四行为 m 个整数 bi,代表 Bob 每个球的分数。
输出格式:
输出共 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,ai,bi≤10;
对于 100% 的数据:1≤n,m≤100000;-10000≤ai,bi≤10000。
题目分析:
首先明确:保证不相等且差异大于积的 1%,这样精度上就不用太担心。
此题有三种方法:
方法一:log法(标算的方法)首先我们知道logaxy=logax+logay。这样对于连乘就可以转化为分别取对数后相加,两者的大小关系是不变的。而对于正负性和0,单独判断。正负性根据负号个数的奇偶判断。而每次取对数都是对绝对值取对数,0直接忽略掉。
PS:c++数学库里自带log,头文件加入#include<cmath>;运用时log(x),底数是e。自带log还有log2(x)log10(x)(底数为2,精度相对最高),没有其它底数的log了。
方法二:相除法 你可以直接一个Alice一个Bob对应相除(短的就给它补1)得到商记做double型,把商乘起来比较与1的大小关系。正负性和0要记得判断。
方法三:极大值个数法你可以设一个极大值如1016,直接连着乘,存入sum[tot],如果大于了1016,就新开一个sum[++tot]存,以此类推,最后比较一下个数,显然,个数多的大,对于个数相同的,可以利用方法二把sum对应相除比较大小。同样记得判正负性和0。
附代码:
方法一:log法
此代码中用到了pair(更简洁),不知道的请百度一下。实际上pair就是一个包含两个数据值的结构体,第一个的名字是first,第二个是second。

#include<iostream>#include<cstring>#include<string>#include<cstdlib>#include<cstdio>#include<ctime>#include<cmath>#include<cctype>#include<iomanip>#include<algorithm>using namespace std;int n,t,x;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;}pair<int,double> find()//pair型的第一维处理正负号和0,第二维处理绝对值取对数的和{    pair<int,double> result=make_pair(1,0);//两维分别赋初值1,0    n=readint();    for(int i=1;i<=n;i++)    {        x=readint();        if(x<0)        {            result.first=-result.first;            result.second+=log(-x);        }        else        {            if(x==0) result.first=0;            else result.second+=log(x);        }    }    return result;}int main(){    //freopen("lx.in","r",stdin);    t=readint();    while(t--)    {        pair<int,double> x1=find();        pair<int,double> x2=find();        double ans1=x1.first*x1.second;//这样相乘就可以方便地直接比较大小了        double ans2=x2.first*x2.second;        if(ans1<ans2) printf("Alice\n");        else printf("Bob\n");    }    return 0;}

方法二:相除法
直接copy的一位同学的

#include<iostream>#include<algorithm>#include<cstdio>#include<cstdlib>#include<string>#include<cstring>#include<cmath>#include<ctime>using namespace std;inline int read(){    int i=0,f=1;    char ch;    ch=getchar();    while(ch>'9'||ch<'0')    {        if(ch=='-')f=-1;        ch=getchar();    }    while(ch>='0'&&ch<='9')    {        i=(i<<1)+(i<<3)+ch-'0';        ch=getchar();    }    return i*f;}int t,n,m,a[100005],b[100005];double c[100005];int main(){    t=read();    while(t--)    {        n=read();        int f1=0,f2=0;        for(int i=1;i<=n;i++)        {            a[i]=read();            if(a[i]<0)            {                f1++;                a[i]=-a[i];            }        }        m=read();        for(int i=1;i<=m;i++)        {            b[i]=read();            if(b[i]<0)            {                f2++;                b[i]=-b[i];            }        }           if(f1%2==1&&f2%2==0)        {            cout<<"Alice"<<endl;            continue;        }        if(f1%2==0&&f2%2==1)        {            cout<<"Bob"<<endl;            continue;        }        bool bz;        if(f1%2==0&&f2%2==0)bz=1;        if(f1%2==1&&f2%2==1)bz=0;        sort(a+1,a+n+1);        sort(b+1,b+n+1);        int p=0;        for(int i=1;i<=max(n,m);i++)        {            if(i>m)b[i]=1;            if(i>n)a[i]=1;            c[i]=double(a[i])/double(b[i]);            if(a[i]==0)            {                p=1;                break;            }            if(b[i]==0)            {                p=2;                break;                          }        }        if(p==1)            if(f2%2==0)            {                cout<<"Alice"<<endl;                continue;            }        if(p==2)        {            if(f1%2==0)            {                cout<<"Bob"<<endl;                continue;                           }            else            {                cout<<"Alice"<<endl;                continue;                           }                   }        sort(c+1,c+max(n,m)+1);        double ans=1;        bool bj=0;        for(int i=1;i<=max(n,m);i++)        {            ans*=c[i];            if(ans>1)            {                bj=1;                break;            }        }        if(bj)            if(!bz)cout<<"Alice"<<endl;            else cout<<"Bob"<<endl;        else            if(bz)cout<<"Alice"<<endl;            else cout<<"Bob"<<endl;         }    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;//flag判断是否有0        }        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)//均不含0        {            if(check1==1&&check2==0) {printf("Alice\n");continue;}            if(check1==0&&check2==1) {printf("Bob\n");continue;}        }        if(flag1==true&&flag2==false)//Alice为0 ,Bob不为0        {            if(check2==1) {printf("Bob\n");continue;}            else {printf("Alice\n");continue;}        }        if(flag1==false&&flag2==true)//Alice不为0 ,Bob为0        {            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;}        }        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;}
原创粉丝点击