2018牛客网暑期ACM多校训练营(第六场)J(脑洞)

题目描述:

    给你一个大小为n的数组,数组中的每一个数由A,B,C,D四个参数根据某个奇怪的代码生成,问你在这n个数中选取2两个数,使得lcm(ai,aj)最大。

题目分析:

    要做出这个题需要一定的脑洞。我们打表可以发现,每次答案可能是最大的数和第二大的数的lcm,或者是最大的数和第三个数的lcm,或者是第二大的数和第三大的数的lcm........我们可以发现,最终的结果必定是在比较大的数集中选出来了。

    因此我们可以大胆猜想,每次我们取前100大,我们每次用O(100*100)的时间暴力求解,最终的答案就是正解。(结果恰好就是如此)。

    可以证明(不会证明)随机两个正整数互质的概率为6/pi^2,因此我们取前100大的数算结果可以满足题目要求。

    (总之这就是一个玄学的题目,需要一定的脑洞)

代码:

    

#include <bits/stdc++.h>
#define maxn 10000005
using namespace std;
typedef unsigned long long ll;
unsigned int n,a,b,c;
ll num[maxn];
unsigned x,y,z;
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
unsigned int tang(){
    unsigned int t;
    x^=x<<16;
    x^=x>>5;
    x^=x<<1;
    t=x;
    x=y;
    y=z;
    z=t^x^y;
    return z;
}
bool cmp(ll x,ll y) {return x>y;}
int main()
{
    int t,cnt=0;
    scanf("%d",&t);
    while(t--){
        scanf("%u%u%u%u",&n,&a,&b,&c);
        x=a,y=b,z=c;
        for(int i=0;i<n;i++){
            num[i]=tang();
        }
        unsigned int k=min(100u,n);
        nth_element(num,num+k,num+n,cmp);//取前k大
        ll ans=0,ans1=0;
        for (int i=0;i<k;i++)
            for (int j=i+1;j<k;j++){
                ans=max(ans,num[i]*num[j]/gcd(num[i],num[j]));
            }
        printf("Case #%d: %llu\n",++cnt,ans);
    }
    return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值