题目描述:
给你一个大小为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;
}