• [cf1285F]Classical


    先枚举$d=gcd$,然后暴力枚举所有$d$的倍数,相当于求出若干个数中最大的互素对

    假设选出的数依从大到小排序后为$a_{i}$,令$g_{i}=min_{(a_{i},a_{j})=1}j$,则答案为$max a_{i}cdot a_{g_{i}}$

    考虑一种比较奇怪的计算$g_{i}$的方式,先求出$tot=sum_{j=1}^{n}[(a_{i},a_{j})=1]$,然后从$n$到1依次删除,直到删除的数中与$a_{i}$互素的数达到了$tot$个

    关于$tot$的计算可以用莫比乌斯反演,即化简为$sum_{d|a_{i}}mu(d)sum_{j=1}^{n}[d|a_{j}]$,记后面的式子为$f(d)$,可以在插入$a_{j}$时处理,那么就可以做到”均摊“单次插入/删除/询问$o(ln n)$

    之后考虑从$n$到1依次去删除,复杂度为$o(n-g_{i})$,但注意到若$g_{i}ge g_{i-1}$那么没有意义,因此从$g_{i-1}$开始统计(即令$n=g_{i-1}$)就可以做到$o(nln^{2}n)$了(枚举$d$+计算$tot$的调和级数和gcd)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 vector<int>v,d[N];
     5 int n,x,vis[N],mu[N],p[N],f[N];
     6 long long ans;
     7 int gcd(int x,int y){
     8     if (!y)return x;
     9     return gcd(y,x%y);
    10 }
    11 void update(int k,int p){
    12     for(int i=0;i<d[k].size();i++)f[d[k][i]]+=p;
    13 }
    14 int query(int k){
    15     int ans=0;
    16     for(int i=0;i<d[k].size();i++)ans+=mu[d[k][i]]*f[d[k][i]];
    17     return ans;
    18 }
    19 int main(){
    20     mu[1]=1;
    21     for(int i=2;i<N-4;i++){
    22         if (!vis[i]){
    23             p[++p[0]]=i;
    24             mu[i]=-1;
    25         }
    26         for(int j=1;(j<=p[0])&&(i*p[j]<N-4);j++){
    27             vis[i*p[j]]=1;
    28             if (i%p[j])mu[i*p[j]]=-mu[i];
    29             else{
    30                 mu[i*p[j]]=0;
    31                 break;
    32             } 
    33         }
    34     }
    35     scanf("%d",&n);
    36     memset(vis,0,sizeof(vis));
    37     for(int i=1;i<=n;i++){
    38         scanf("%d",&x);
    39         vis[x]=1;
    40     }
    41     for(int i=1;i<N-4;i++)
    42         for(int j=i;j<N-4;j+=i)d[j].push_back(i);
    43     for(int i=1;i<N-4;i++){
    44         v.clear();
    45         for(int j=i;j<N-4;j+=i)
    46             if (vis[j])v.push_back(j/i);
    47         int m=v.size();
    48         for(int j=0;j<m;j++)update(v[j],1);
    49         for(int j=m-1,k=0;j>=0;j--){
    50             int sum=query(v[j]);
    51             while (sum){
    52                 if (gcd(v[j],v[k])==1){
    53                     sum--;
    54                     ans=max(ans,1LL*v[j]*v[k]*i);
    55                 }
    56                 update(v[k++],-1);
    57             }
    58             if (!j)
    59                 while (k<m)update(v[k++],-1);
    60         }
    61     }
    62     printf("%lld",ans);
    63 }
    View Code
  • 相关阅读:
    jekyll+github搭建个人博客总结
    ES6-let命令
    Ajax-快速上手前后端交互
    第一次项目总结——校园博览会
    Python获取exe文件版本
    @JsonFormat与@DateTimeFormat注解的使用
    前后端时间转化
    左右flex布局
    fastjson将json字符串转化成map的五种方法
    RestTemplate 发送post请求
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14178166.html
Copyright © 2020-2023  润新知