zoukankan      html  css  js  c++  java
  • CF1285F Classical?

    Link
    (A=max(a_i))
    先枚举(g),然后计算满足(gcd(a_i,a_j)=g)的答案。
    考虑从大到小枚举集合中的数,假如现在枚举到(x),若存在(y>x)满足(gcd(x,y)=g),那么所有((x,y))内的数都不会对答案有贡献了。
    因此我们可以弹栈直到栈中没有数与(x)互质,弹栈的时候计算贡献。
    随之而来的问题就是如何计算栈中有多少与(x)互质的数,设(cnt_x)表示(x)的出现次数,考虑经典反演:
    (sumlimits[gcd(x,y)=1]cnt_y=sumlimits_{d|x}mu(d)sumlimits_{d|y}cnt_y)
    那么我们维护(cnt'_x=sumlimits_{x|y}cnt_y)即可。
    这样做的时间复杂度为(O(nlog^2n))
    那么我们最开始将(a_i)的所有因数都加入集合,然后只需要枚举(gcd(a_i,a_j)=1)跑一遍即可得到答案。
    最后记得特判(operatorname{lcm}(a_i,a_i))的情况。
    时间复杂度为(O(Alog A))

    #include<cctype>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using i64=long long;
    const int N=100007;
    int vis[N],cnt[N],mu[N];std::vector<int>fac[N],stk;
    int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
    int main()
    {
        int n=read(),m=0;i64 ans=0;mu[1]=1;
        for(int i=1,x;i<=n;++i) m=std::max(m,x=read()),vis[x]=1;
        for(int i=1;i<=m;++i) for(int j=i+i;j<=m;j+=i) mu[j]-=mu[i];
        for(int i=1;i<=m;++i) for(int j=i;j<=m;j+=i) if(vis[i]|=vis[j],mu[i]) fac[j].push_back(i);
        for(int i=m;i;--i)
        {
    	int num=0;
    	if(!vis[i]) continue;
    	for(int j:fac[i]) num+=mu[j]*cnt[j];
            for(;num;stk.pop_back())
    	{
    	    int last=num;
    	    for(int j:fac[stk.back()]) if(--cnt[j],!(i%j)) num-=mu[j];
    	    if(last^num) ans=std::max(ans,1ll*i*stk.back());
            }
    	for(int j:fac[i]) ++cnt[j];
    	stk.push_back(i);
        }
        printf("%lld",std::max(ans,1ll*m));
    }
    
  • 相关阅读:
    Jmeter生成HTML报告
    Python多线程(生成动态参数)
    小程序利用canvas生成图片加文字,保存到相册
    小程序商城数量加减效果
    支付宝小程序tab切换滑动
    数据排序,从小到大,从大到小,ajax
    小程序上拉加载更多,onReachBottom
    小程序tab导航切换样式
    小程序动画Animation,高度增加动画形式,图标旋转动画形式
    iview weapp icon组件自定义图标 小程序
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12918287.html
Copyright © 2011-2022 走看看