• 【题解】「MCOI-02」Convex Hull 凸包


    题目戳我

    ( ext{Solution:})

    [sum_{i=1}^n sum_{j=1}^n ho(i) ho(j) ho(gcd(i,j)) ]

    [=sum_{d=1}^n ho(d)sum_{i=1}^n sum_{j=1}^n ho(i) ho(j) ho(gcd(i,j))[gcd(i,j)=d] ]

    [=sum_{d=1}^n ho(d)sum_{i=1}^frac{n}{d}sum_{j=1}^frac{n}{d} ho(i*d) ho(j*d)[gcd(i,j)=1] ]

    [=sum_{d=1}^n ho(d) sum_{k=1}^frac{n}{d}mu(k)sum_{i=1}^frac{n}{kd}sum_{j=1}^frac{n}{kd} ho(i*kd) ho(j*kd) ]

    [=sum_{T=1}^nsum_{d|T} ho(d)mu(frac{T}{d})sum_{i=1}^frac{n}{T}sum_{j=1}^frac{n}{T} ho(i*T) ho(j*T) ]

    [=sum_{T=1}^n sum_{i=1}^frac{n}{T}sum_{j=1}^frac{n}{T} ho(i*T) ho(j*T) ]

    ( ho*mu=1*1*mu=1*e)即值始终为(1.)

    这题所学到的主要是线性筛约数个数( ho)

    前提:唯一分解定理 (n=prod_{i=1}^k p_i^{a_i}, ho(n)=prod (a_i+1))

    (g)是最小质因数的次数,(t)是约数个数。

    对于质数:显然(g=1,t=2(1,p).)

    (n=i*p[j]:)

    (iequiv 0mod p[j],g[n]=g[i]+1,t[n]=frac{t[i]*(g[n]+1)}{g(n)})

    否则(g[n]=1,t[n]=t[i]*2.)

    解释:对于非质数的第二种情况,最小质因子次数一定是一个质数不必解释,而因子个数由于多了一个质因子,所以由上述唯一分解定理会使得原来的(g)变为两倍(多乘了一个(c_p+1,c_p=1.)

    对于非质数的第一种情况,最小质因子一定是当前的(p[j],)所以最小质因子次数就是(g[i]+1,)而约数个数需要先把(i)(p[j])因子除尽再乘上当前的这个,实际上就是把(c_{p[j]})加了一。

    于是这题可以在不用 Dirichlet前缀和 的情况下做到(O(nln n+nln n).)

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=2e6;
    int n,m,pp,vis[MAXN+1],cnt,p[MAXN+1],t[MAXN+1],g[MAXN+1],Tn[MAXN+1],Tm[MAXN+1],ans;
    inline int add(int x,int y){return (x+y)%pp;}
    inline int mul(int x,int y){return 1ll*x*y%pp;}
    inline void predo(){
    	t[1]=1;
    	for(int i=2;i<=MAXN;++i){
    		if(!vis[i])p[++cnt]=i,g[i]=1,t[i]=2;
    		for(int j=1;j<=cnt&&i*p[j]<=MAXN;++j){
    			vis[i*p[j]]=1;
    			if(i%p[j]==0){
    				g[i*p[j]]=g[i]+1;
    				t[i*p[j]]=mul(t[i]/g[i*p[j]],(g[i*p[j]]+1));
    				break;
    			}
    			g[i*p[j]]=1;
    			t[i*p[j]]=t[i]<<1;
    		}
    	}
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&pp);
    	predo();
    	if(n>m)swap(n,m);
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=n/i;++j)
    			Tn[i]=add(Tn[i],t[i*j]);
    	for(int i=1;i<=m;++i)
    		for(int j=1;j<=m/i;++j)
    			Tm[i]=add(Tm[i],t[i*j]);
    	for(int T=1;T<=n;++T)
    		ans=add(ans,mul(Tn[T],Tm[T]));
    	printf("%d
    ",ans);
    	return 0;
    } 
    
  • 相关阅读:
    记一次简单的正则表达式匹配实践
    使用readlines()读取文件时出现/n及其解决办法
    浅谈http和https
    JVM GC回收原理的认识
    Mysql中语言分类和区别
    关于storm程序性能压测记录及总结
    Java 集合框架
    MySQL binlog底层主从同步原理
    Docker-Compose安装
    gcc手动安装
  • 原文地址:https://www.cnblogs.com/h-lka/p/13693280.html
Copyright © 2020-2023  润新知