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;
}
posted @ 2025-04-23 21:42  Marinaco  阅读(24)  评论(0)    收藏  举报
//雪花飘落效果