Problem B. gWheels Google APAC 2016 University Test Round B

pedal group的wheel记为p1,extra group的wheel记为e1,e2,tear group的wheel记为t1。

满足target ratio即为p1/e2*e2/t1=P/Q,namely,p1*e2*Q=e1*t1*P。那么可以枚举p1*e2的所有值,在搜索是否存在对应的组合e1*t1满足不等式。

可以预处理将所有的p1*e2存在数组leftarr中,将所有的e1*t1存在数组rightarr中,将leftarr排好序,就可以在给定一个p1*e2的值时,二分查找判断是否存在使得等式成立的e1*t1。

如果二分查找到的e1*t1是同一个extra geal,因为rightarr是排好序的,如果结果是yes,那么mid-1,mid+1处至少存在一个gear可以满足等式并且不是同一个extra geal。否则就不存在满足条件的两个extra geal。

感觉等式两边的值可能会溢出,所以用long long保险些。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>

using namespace std;

//2016 Round B Problem B. gWheels
int T;
const int maxn=2010;
int P;
int M;
int Q;
int Np;
int Nt;
int Ne;
long long arrp[maxn];
long long arrt[maxn];
long long arre[maxn];
pair<long long,int>leftarr[maxn*maxn];
pair<long long,int>rightarr[maxn*maxn];
int kgcd(int a,int b)
{
    if(a==0) return b;
    if(b==0) return a;
    if(!(a&1)&&!(b&1)) return kgcd(a>>1,b>>1)<<1;
    else if(!(b&1)) return kgcd(a,b>>1);
    else if(!(a&1)) return kgcd(a>>1,b);
    else return kgcd(abs(a-b),min(a,b));
}
bool cmp(pair<int,int>a,pair<int,int>b)
{
    if(a.first==b.first)
    {
        return a.second<b.second;
    }
    return a.first<b.first;
}
bool binarysearch(long long val,int idxl)
{
    int left=0;
    int right=Nt*Ne;
    int mid=(left+right)/2;
    while(left<=right)
    {
        mid=(left+right)/2;
        long long valr=rightarr[mid].first;
        int idxr=rightarr[mid].second;
        if(val*Q==valr*P)
        {
            if(idxl!=idxr)
            {
                return true;
            }
            else if(mid>0&&rightarr[mid-1].first==val)
            {
                return true;
            }
            else if(mid<Nt*Ne-1&&rightarr[mid+1].first==val)
            {
                return true;
            }
            return false;
        }
        else if(val*Q<valr*P)//valr is too large
        {
            right=mid-1;
        }
        else if(val*Q>valr*P)//valr is too small
        {
            left=mid+1;
        }
    }
    return false;
}
int main()
{
    freopen("B-large-practice.in","r",stdin);
//    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        printf("Case #%d:\n",ca);
        memset(arrp,0,sizeof(arrp));
        memset(arrt,0,sizeof(arrt));
        memset(arre,0,sizeof(arre));
        scanf("%d %d %d",&Np,&Ne,&Nt);
        for(int i=0;i<Np;i++)
        {
            scanf("%lld",&arrp[i]);
        }
        for(int i=0;i<Ne;i++)
        {
            scanf("%lld",&arre[i]);
        }
        for(int i=0;i<Nt;i++)
        {
            scanf("%lld",&arrt[i]);
        }
        int cnt=0;
        for(int i=0;i<Np;i++)
        {
            for(int j=0;j<Ne;j++)
            {
                leftarr[cnt++]=make_pair(arrp[i]*arre[j],j);
            }
        }
        cnt=0;
        for(int i=0;i<Nt;i++)
        {
            for(int j=0;j<Ne;j++)
            {
                rightarr[cnt++]=make_pair(arrt[i]*arre[j],j);
            }
        }
        sort(rightarr,rightarr+cnt,cmp);
        scanf("%d",&M);
        for(int i=0;i<M;i++)
        {
            scanf("%d %d",&P,&Q);
            int g=kgcd(P,Q);
            P/=g;
            Q/=g;
            bool ans=false;
            for(int i=0;i<Np*Ne;i++)
            {
                ans=binarysearch(leftarr[i].first,leftarr[i].second);
                if(ans==true)
                {
                    printf("Yes\n");
                    break;
                }
            }
            if(ans==false)
            {
                printf("No\n");
            }
        }

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值