• BZOJ3994: [SDOI2015]约数个数和


    BZOJ3994: [SDOI2015]约数个数和


    题目描述

    传送门

    题目分析

    求的东西简明扼要,

    [sum_{i=1}^{N}sum_{j=1}^{m}d(ij) ]

    但是有个需要知道的是

    [d(ij)=sum_{xmid i}sum_{ymid j}[gcd(x,y)=1] ]

    然后可以开始开心的推式子。

    根据反演套路,设两个函数

    [f(d)=sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=d] ]

    [F(n)=sum_{nmid d}f(d)=lfloor frac Nd floor lfloor frac Md floor ]

    根据莫比乌斯反演可以得到:

    [f(n)=sum_{nmid d}mu(frac dn)F(d) ]

    (d(i,j))代回原来的式子并化简:

    [egin{align} Ans&=sum_{i=1}^{N}sum_{j=1}^{M}d(ij) \ &=sum_{i=1}^{N}sum_{j=1}^{M}sum_{xmid i}sum_{ymid j}[gcd(x,y)=1] 根据mu的性质把它代进去\ &=sum_{i=1}^{N}sum_{j=1}^{M}sum_{xmid i}sum_{ymid j}sum_{dmid gcd(x,y)}mu(d) 然后更换枚举约数为枚举d \ &=sum_{i=1}^{N}sum_{j=1}^{M}sum_{xmid i}sum_{ymid j}sum_{d=1}^{min(N,M)}mu(d) imes [dmid gcd(x,y)]\ &=sum_{d=1}^{min(N,M)}mu(d)sum_{i=1}^{N}sum_{j=1}^{M}sum_{xmid i}sum_{ymid j}[dmid gcd(x,y)]\ &=sum_{d=1}^{min(N,M)}mu(d)sum_{x=1}^{N}sum_{y=1}^{M}[dmid gcd(x,y)]lfloor frac {N}{x} floor lfloor frac{M}{y} floor \ &=sum_{d=1}^{min(N,M)}mu(d)sum_{x=1}^{lfloorfrac{N}{d} floor}sum_{y=1}^{lfloorfrac{M}{y} floor}lfloorfrac{N}{dx} floorlfloorfrac{M}{dy} floor\ &=sum_{d=1}^{min(N,M)}mu(d)(sum_{x=1}^{lfloorfrac{n}{d} floor}lfloorfrac{n}{dx} floor)(sum_{y=1}^{lfloorfrac{m}{d} floor}lfloorfrac{m}{dy} floor) end{align} ]

    明显,推到这里了之后就可以在(O(n))的时间内求出了。

    对于多组数据,可以进行整除分块,再将这个式子优化成(O(sqrt n))的。

    是代码呢

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=1e5+7;
    #define ll long long
    ll sum[MAXN],g[MAXN];
    int mu[MAXN],prime[MAXN];
    bool vis[MAXN];
    int n,m;
    inline void get_mu(int N)
    {
    	mu[1]=1;
    	for(int i=2;i<=N;i++){
    		if(!vis[i]){
    			mu[i]=-1;
    			prime[++prime[0]]=i;
    		}
    		for(int j=1;j<=prime[0];j++){
    			if(prime[j]*i>N) break;
    			vis[prime[j]*i]=1;
    			if(i%prime[j]==0) break;
    			else mu[i*prime[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<=N;i++) sum[i]=sum[i-1]+mu[i];
    	for(int i=1;i<=N;i++){
    		ll ans=0;
    		for(int l=1,r;l<=i;l=r+1){
    			r=(i/(i/l));
    			ans+=1ll*(r-l+1)*(i/l);
    		}
    		g[i]=ans;
    	}
    }
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        while(ch=='-')c*=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    int main()
    {
    	int T=read();
    	get_mu(50000);
    	while(T--){
    		n=read(),m=read();
    		int r=0,mx=min(n,m);
    		ll ans=0;
    		for(int l=1;l<=mx;l=r+1){
    			r=min((n/(n/l)),(m/(m/l)));
    			ans+=1ll*(sum[r]-sum[l-1])*(g[n/l])*g[m/l];
    		}
    		printf("%lld
    ", ans);
    	}
    }
    
  • 相关阅读:
    ajax处理返回的json数据
    (转)JavaScript Trim() IE 不支持 问题解决 .
    ajax乱码,asp,php,jsp
    常用工具软件
    给DIV添加滚动条
    java递归菜单树转换成json字符串
    将请求的数据以json(plain)输出有乱码
    json穿
    乱码问题
    getRequestURI,getRequestURL的区别
  • 原文地址:https://www.cnblogs.com/victorique/p/10385823.html
Copyright © 2020-2023  润新知