A. easy math problem
题目:
...
题意:
给定一个数组,选择三个数 ai,aj,ak 满足 ai*b=aj , aj*b=ak
统计这样的(i,j,k)(不需要使i<j<k)三元组有多少个?
思路:
发现条件类似于等差数列 : aj/ai =b ,ak/aj=b
当b不等于1时,那么 ai , aj, ak 都不相等
由乘法原理得出这个三元组对答案的贡献为 cnt[ai] x cnt[aj] x cnt[ak]
当b等于1时,由于位置顺序不是必须从小到大
那么其实是在cnt>=3的元素中间挑选三个组成三元组
即An(3)=n x (n-1) x(n-2)
具体实现:不妨先对元素计数后将数组排序去重,遍历枚举每一个元素的因子(枚举公比q)(当然q!=1),将该数的前后两者统计计数
对于相同的元素另行统计
时间复杂度O(N x sqrt(ai))
int tot[maxn];
void solve(){
int n;cin>>n;
vector<int>a(n+1);
for(int i=1;i<=1e6;i++)tot[i]=0;
int big=0;
vector<int>x;
rep(i,1,n){
cin>>a[i];
big=max(big,a[i]);
tot[a[i]]++;
}
sort(a.begin()+1,a.end());
for(int i=1;i<=n;i++){
if(x.size()&&x.back()==a[i])continue;
x.pb(a[i]);
}
int ans=0;
rep(i,0,x.size()-1){
int ok=0;
for(int j=2;j*j<=x[i];j++){
if(x[i]%j==0&&x[i]*j<=big){
int k=x[i]/j;
if(j==x[i]||k==x[i])ok=1;
// debug(a[i]);
// debug(j);
// debug(k);
ans+=tot[x[i]]*tot[x[i]/j]*tot[x[i]*j];
if(k!=1&&j!=k&&x[i]*k<=big)ans+=tot[x[i]]*tot[x[i]/k]*tot[x[i]*k];
}
}
if(!ok&&x[i]*x[i]<=big&&x[i]!=x[i]*x[i])ans+=(tot[1]*tot[x[i]]*tot[x[i]*x[i]]);
}
for(int i=1;i<=big;i++){
if(tot[i]>=3){
ans+=tot[i]*(tot[i]-1)*(tot[i]-2);
}
}
cout<<ans<<endl;
}

浙公网安备 33010602011771号