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

    CF1285F Classical?

    太神仙了。Orz (color{black}{ exttt{c}}color{black}{ exttt{yn2006}})

    这个值域 (10^5) 使我们想到枚举 (gcd)

    假设我们枚举 (gcd=t) ,那么我们扫描所有 (t) 的倍数 (x),把 (dfrac{x}{t}) 都丢进一个数组,并且从大到小排序

    嗯,直觉是数越大 (operatorname{lcm}) 也就可能越大。只不过有可能会有不互质的情况导致又被约掉一些因子。

    又发现我们只需要在数组里的数互质的情况统计贡献即可,不互质的话说明 (gcd>t) ,会在别的地方被统计到。

    那么我们只需要找到最大的与它互质的数即可!于是从大到小排序就没错了。

    考虑按顺序把这个数组里的东西丢进栈。

    我们发现只需要保留一个与这个数互质的数,其余全都可以弹掉。后面的数找不到互质的数也没关系,因为它们只有与更大的数配对才有可能更新答案。

    而找到最大的与它互质的数可以通过找到栈中有几个与它互质的数然后不断弹栈即可。

    至于找到一个集合内有几个与它互质的数,这是个人口普查形式的莫反。但是我居然推了10来分钟,还是写一写吧(一个月没搞莫反就忘了)

    (m=max{a_i })(c_i) 表示 (i) 在集合中的出现次数。

    [sum_{i=1}^{m}[gcd(ic_i,x)==1]\ =sum_{i=1}^{m}sum_{d|gcd(ic_i,x)}mu(d)\ =sum_{d|x}mu(d)sum_{i=1}^{m}[d|i]c_{i}\ =sum_{d|x}mu(d)sum_{i=1}^{frac{m}{d}}c_{id} ]

    考虑对于每一个 (d) 维护 (f_d=sum_{i=1}^{frac{m}{d}}c_{id}),每次加入或删除一个数 (x) 只会影响到 (d|x)(f_d) ,而 (id=x) ,直接修改就行。

    复杂度是 (O(sum sigma(i)^2))(sigma(i)) 表示 (i) 的因数个数。实测 (1e5) 大概 (9e7) ,CF随便跑。

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mkp(x,y) make_pair(x,y)
    #define pb(x) push_back(x)
    #define sz(v) (int)v.size()
    typedef long long LL;
    typedef double db;
    template<class T>bool ckmax(T&x,T y){return x<y?x=y,1:0;}
    template<class T>bool ckmin(T&x,T y){return x>y?x=y,1:0;}
    #define rep(i,x,y) for(int i=x,i##end=y;i<=i##end;++i)
    #define per(i,y,x) for(int i=y,i##end=x;i>=i##end;--i)
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f?x:-x;
    }
    #define N 100005
    
    int n,m,a[N],stk[N],top,mu[N],pri[N/10],pct,b[N],c[N],cnt[N];
    LL ans;
    bool vis[N];
    vector<int>d[N];
    void init(){
    	mu[1]=1;
    	rep(i,2,m){
    		if(!vis[i])pri[++pct]=i,mu[i]=-1;
    		for(int j=1;j<=pct&&i*pri[j]<N;++j){
    			vis[i*pri[j]]=1;
    			if(i%pri[j]==0){mu[i*pri[j]]=0;break;}
    			mu[i*pri[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<=m;++i)
    		for(int j=1;i*j<=m;++j)
    			d[i*j].pb(i);
    }
    void upd(int x){
    	rep(i,0,sz(d[x])-1)++c[d[x][i]];
    }
    void del(int x){
    	rep(i,0,sz(d[x])-1)--c[d[x][i]];
    }
    int calc(int x){
    	int res=0;
    	rep(i,0,sz(d[x])-1)
    		res+=mu[d[x][i]]*c[d[x][i]];
    	return res;
    }
    signed main(){
    	n=read();
    	rep(i,1,n)a[i]=read(),ckmax(m,a[i]),++cnt[a[i]];
    	sort(a+1,a+n+1,greater<int>());
    	init();
    	rep(t,1,m){
    		b[0]=0;
    		for(int i=1;i*t<=m;++i)
    			rep(j,1,cnt[i*t])b[++b[0]]=i;
    		reverse(b+1,b+b[0]+1);
    		rep(i,1,b[0]){
    			int now=calc(b[i]);
    			while(now>=1){
    				if(__gcd(stk[top],b[i])==1){
    					if(now==1)break;
    					else --now;
    				}
    				del(stk[top]),--top;
    			}
    			if(now==1)ckmax(ans,1ll*b[i]*stk[top]*t);
    			stk[++top]=b[i],upd(b[i]);
    		}
    		while(top)del(stk[top--]);
    	}
    	printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    Server 对象
    Response 对象
    bzoj 5252: [2018多省省队联测]林克卡特树
    bzoj 2167: 公交车站
    bzoj 5315: [Jsoi2018]防御网络
    bzoj 5319: [Jsoi2018]军训列队
    bzoj 4161: Shlw loves matrixI
    bzoj 4942: [Noi2017]整数
    bzoj 2648: SJY摆棋子
    kd-tree 小结
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14028421.html
Copyright © 2011-2022 走看看