题目链接:
题目大致意思:
Mihai和Slavic正在观察一群青蛙,这些青蛙编号从1到n,初始位置都在点0处。青蛙i每跳一次可以跳跃ai单位长度。
每秒钟,青蛙i向前跳跃ai单位长度。在青蛙开始跳跃之前,Slavic和Mihai可以在一个坐标上放置一个陷阱,以便捕捉到所有将经过该坐标的青蛙。
然而,孩子们不能离开自己的家太远,所以他们只能在前n个点上放置陷阱(也就是坐标在1到n之间的点),并且孩子们不能在点0处放置陷阱,因为他们害怕青蛙。
你能帮助Slavic和Mihai找出使用一个陷阱可以捕捉到的青蛙的最大数量吗?
输入:
第一行输入一个整数t(1≤t≤100)——测试用例的数量。
每个测试用例的描述如下所示。
每个测试用例的第一行是一个整数n(1≤n≤2⋅10^5)——青蛙的数量,也就是Mihai和Slavic能够移动来放置陷阱的距离。
每个测试用例的第二行是n个整数a1,…,an(1≤ai≤10^9)——对应青蛙的跳跃长度。
保证所有测试用例中n的总和不超过2⋅10^5。
输出:
对于每个测试用例,输出一个整数——使用一个陷阱可以捕捉到的青蛙的最大数量。
思路:
先把青蛙的跳跃长度挨个输进frog数组,再在判断每一个跳跃长度有无超过n(超过就放弃,因为陷阱最远就到n),接着把小于n的跳跃步数作为下标,ma[frog[i]]++,记录每一种跳法的青蛙有几只(不用map因为这个跳跃步数不会超过数组的存储范围,数组就可以存,用map时间上会慢一点)。
然后再挨个处理没一个位置上有几只青蛙可以跳到,从1开始,到j*j=i结束,如果i%j=0,在进行分支判断:
一:如果j*j=i:则num+=ma[j]
二:除一以外情况:num+=ma[j],num+=ma[i/j]
(我们可以理解为,a*b=i,也就是两个数的乘积为当前位置,因为我们只到j*j=i就结束了,所以有的乘积会大于j,例如:3*9=27,j到5就结束了)
ans取最大的num,最后再输出ans。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6;
int frog[N],ma[N];
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
int n,ans=0,cnt=0;
cin>>n;
for(int i=1;i<=n;i++){
ma[i]=0;
cin>>frog[i];
}
for(int i=1;i<=n;i++) if(frog[i]<=n) ma[frog[i]]++;
for(int i=1;i<=n;i++){
int num=0;
for(int j=1;j*j<=i;j++){
if(i%j==0){
if(j*j==i) num+=ma[j];
else num+=ma[j],num+=ma[i/j];
}
}
ans=max(ans,num);
}
cout<<ans<<"\n";
}
}