• 【[SDOI2015]约数个数和】


    慢慢化柿子吧

    要求的是这个

    [sum_{i=1}^Nsum_{j=1}^Md(ij) ]

    神奇的约数个数函数有一个这样的性质

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

    试着从唯一分解定理的角度去理解,将(i,j)分别分解质因数

    显然(d(ij))应该等于每一个(p)(i,j)中分解出来的指数加起来加1再相乘

    所以分别枚举所有约数的话,保证这对约数互质就可以求出所有约数了

    之后现在的答案变成了

    [sum_{i=1}^Nsum_{j=1}^Msum_{x|i}sum_{y|j}[(x,y)=1] ]

    一看就很烦人啊,把(x,y)放到前面来枚举

    [sum_{x=1}^Nsum_{y=1}^M[(x,y)=1]sum_{x|i}sum_{y|j}1 ]

    显然后面那个东西就是

    [left lfloor frac{N}{x} ight floor imes left lfloor frac{M}{y} ight floor ]

    于是答案变成了

    [sum_{x=1}^Nsum_{y=1}^M[(x,y)=1]left lfloor frac{N}{x} ight floor imes left lfloor frac{M}{y} ight floor ]

    开始套路了

    [f(n)=sum_{i=1}^Nsum_{j=1}^M[(i,j)=n]left lfloor frac{N}{i} ight floor imes left lfloor frac{M}{j} ight floor ]

    [F(n)=sum_{i=1}^Nsum_{j=1}^M[n|(i,j)]left lfloor frac{N}{i} ight floor imes left lfloor frac{M}{j} ight floor ]

    [=sum_{i=1}^{ left lfloor frac{N}{i} ight floor}sum_{j=1}^{ left lfloor frac{M}{j} ight floor} left lfloor frac{N}{in} ight floor left lfloor frac{M}{jn} ight floor ]

    显然就有

    [F(n)=sum_{n|d}f(d) ]

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

    因为我们要求的只有(f(1))

    所以

    [Ans=sum_{d=1}^Nmu(d)sum_{i=1}^{left lfloor frac{N}{i} ight floor}sum_{j=1}^{left lfloor frac{M}{j} ight floor}left lfloor frac{N}{id} ight floor left lfloor frac{M}{jd} ight floor ]

    我们发现如果(frac{N}{d})(frac{M}{d})固定了,后面这个柿子就非常好求了

    就是(frac{N}{d})(frac{M}{d})的约数个数前缀和

    于是我们可以线筛约数个数函数和(mu)之后就可以了

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define LL long long
    #define min(a,b) ((a)<(b)?(a):(b))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define re register
    #define maxn 50005
    inline int read()
    {
    	char c=getchar();
    	int x=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();
    	return x;
    }
    int p[maxn>>1],f[maxn],pre[maxn],mu[maxn],d[maxn],t[maxn];
    int T,n,m;
    int main()
    {
    	f[1]=1,mu[1]=1,d[1]=1;
    	for(re int i=2;i<=50000;i++)
    	{
    		if(!f[i]) p[++p[0]]=i,mu[i]=-1,d[i]=2,t[i]=1;
    		for(re int j=1;j<=p[0]&&p[j]*i<=50000;j++)
    		{
    			f[p[j]*i]=1;
    			if(i%p[j]==0)
    			{
    				d[p[j]*i]=d[i]/(t[i]+1)*(t[i]+2);
    				t[p[j]*i]=t[i]+1;
    				break;
    			}
    			d[p[j]*i]=d[p[j]]*d[i];
    			mu[p[j]*i]=-1*mu[i];
    			t[p[j]*i]=1;
    		}
    	}
    	for(re int i=1;i<=50000;i++) pre[i]=pre[i-1]+mu[i],d[i]+=d[i-1];
    	T=read();
    	while(T--)
    	{
    		n=read(),m=read();
    		if(n>m) std::swap(n,m);
    		LL ans=0;
    		for(re int l=1,r;l<=n;l=r+1)
    		{
    			r=min(n/(n/l),m/(m/l));
    			ans+=(LL)d[n/l]*d[m/l]*(pre[r]-pre[l-1]);
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    项目数据分析师CPDA印章
    一点想法
    该减肥啦
    PMP证书到手
    Google App Engine之初体验
    转K线理论初级三
    黄小琥没那么简单
    使用webapp框架再现Hello World
    Google App Engine之介绍篇
    转股票中KDJ线的详细分析
  • 原文地址:https://www.cnblogs.com/asuldb/p/10205674.html
Copyright © 2020-2023  润新知