要塞任务
时间限制: 1 Sec 内存限制: 128 MB
题目描述
你的要塞⾥有N名随从,每名随从有⼀个战⽃⼒值Ai,不同随从的战⽃⼒可以相同,且永远不超过N。⼀个要塞任务需要恰好M个随从参与。
要塞任务的奖励取决于随从们配合的程度。(显⽽易见地),M个随从的联合战⽃⼒A为它们战⽃⼒的最⼤公约数,⽽任务的奖励分数定义为ϕ(A)。
求最⼤可能的奖励分数。
输入
本题有多组数据,第⼀⾏为数据组数T(T≤10)。
接下来每组数据有两⾏,第⼀⾏两个整数N,M,第⼆⾏N个整数Ai(N,M,Ai≤100000)。
输出
最多的奖励分数。
样例输入 Copy
1
5 2
1 4 6 9 12
样例输出 Copy
2
提示
样例解释:派出编号为6和12的随从,联合战⽃⼒为3,奖励分数2。
这个题有两个要求的点,一个是预处理欧拉函数,在有限的时间复杂度内求出 k 个数的最大公约数。
对于第一个,预处理 1 ~ 1e5 的欧拉函数时间完全够用。
对于第二个,一开始sblj的去求每个数的约数让后开个哈希数组记录个数,果不其然就超时了。既然枚举数找出因子不行,那么可以试试枚举因子找数。对于 1 ~ mx 的每个数,依次枚举以它为因子的数,如果枚举到了 a 中的数,那么 cnt ++ ,当cnt >= m 的时候符合条件。也不是很会算时间复杂度,反正这样就能水过去了。。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=100010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;
int n,m;
int a[N],has[N];
LL euler[N];
LL get_ol(int x)
{
LL res=x;
for(int i=2;i<=x/i;i++)
if(x%i==0)
{
res=res*(i-1)/i;
while(x%i==0)
x/=i;
}
if(x>1) res=res*(x-1)/x;
return res;
}
void init()
{
for(int i=1;i<=1e5+5;i++)
euler[i]=get_ol(i);
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
init();
int t; cin>>t;
while(t--)
{
memset(has,0,sizeof has);
scanf("%d%d",&n,&m);
int mx=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
has[a[i]]++;
mx=max(mx,a[i]);
}
LL ans=0;
for(int i=1;i<=mx;i++)
{
if(ans>=euler[i]) continue;
LL sum=0;
for(int j=i;j<=mx;j+=i)
{
sum+=has[j];
if(sum>=m) break;
}
if(sum>=m) ans=max(euler[i],ans);
}
printf("%lld\n",ans);
}
return 0;
}
/*
*/