题目
#Solution
根据裴蜀定理可得:容量为 v1,v2,.....vk的 k个瓶子所能倒出的最小值为 gcd(v1,v2,...,vk)
其实这结论我是猜出来的,但是确实可以从充分性和必要性方面分别证明
然后问题等价为: n个数里选 k个,使它们的 gcd最小,可以把 n个数所有因子算出后排序,如果有一个因子出现次数 >=k,那这个因子就是可行的,从大到小枚举就可以得出最大值
#Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,k,i,j,x,tmp,p[5000002],cnt;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
int main(){
n=read();k=read();
for (i=0;i<n;i++){
x=read();
for (j=1;(ll)j*j<=x;j++)
if (x%j==0) p[++cnt]=j,p[++cnt]=x/j;
if ((ll)(j-1)*(j-1)==x) cnt--;
}
sort(p+1,p+cnt+1);
tmp=1;
for (i=cnt;i>=0;i--)//注意要包括0,不包括可能能A,但是2 2 4 9就会WA
if (p[i]==p[i+1]) tmp++;
else{
if (tmp>=k){
printf("%d",p[i+1]);
return 0;
}
tmp=1;
}
}
下面这个洛谷rank2,bzoj前20页都没有。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1000007;
int n,k,i,j,x,tmp,p[N],cnt[N],t,ans;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
inline int ha(int x){
int v=x%N;
for (;p[v] && p[v]!=x;v=v==N-1?0:v+1);
return v;
}
int main(){
n=read();k=read();
for (i=0;i<n;i++){
x=read();
for (j=1;(ll)j*j<=x;j++)
if (x%j==0){
t=ha(j);
cnt[t]++;
p[t]=j;
if (j!=x/j){
t=ha(x/j);
cnt[t]++;
p[t]=x/j;
}
}
}
for (i=0;i<N;i++)
if (cnt[i]>=k && p[i]>ans) ans=p[i];
printf("%d",ans);
}