• P3327 [SDOI2015]约数个数和


    洛谷题目链接

    挺简单的数论题

    主要要知道一个式子:$$d(i imes j)=sumlimits_{x|i} sumlimits_{y|j} [gcd(x,y)=1]$$

    具体证明其实挺简单的,这里给出一个大佬的博客

    那么我们需要求的式子就是:$$sumlimits_{i=1}^N sumlimits_{j=1}^M sumlimits_{x|i} sumlimits_{y|j} [gcd(x,y)=1]$$

    分组一下:$$sumlimits_{i=1}^N [x|i] sumlimits_{j=1}^M [y|j] [gcd(x,y)=1]$$

    按照套路改为枚举(x,y):$$sumlimits_{x=1}^N leftlfloor frac{N}{x} ight floor sumlimits_{y=1}^M leftlfloor frac{M}{y} ight floor [gcd(x,y)=1]$$

    套路的反演也行,不过这里用的是莫比乌斯函数的性质:$$sumlimits_{x=1}^N leftlfloor frac{N}{x} ight floor sumlimits_{y=1}^M leftlfloor frac{M}{y} ight floor sumlimits_{d|gcd(x,y)} mu (d)$$

    改为枚举(d)并提前:$$sumlimits_{d=1}^N sumlimits_{x=1}^N sumlimits_{y=1}^M [d|gcd(x,y)] mu (d) leftlfloor frac{N}{x} ight floor leftlfloor frac{M}{y} ight floor$$

    [sumlimits_{d=1}^N sumlimits_{x=1}^{leftlfloor frac{N}{d} ight floor} sumlimits_{y=1}^{leftlfloor frac{M}{d} ight floor} mu (d) leftlfloor frac{N}{dx} ight floor leftlfloor frac{M}{dy} ight floor ]

    分组:$$sumlimits_{d=1}^N mu (d) sumlimits_{x=1}^{leftlfloor frac{N}{d} ight floor} leftlfloor frac{N}{dx} ight floor sumlimits_{y=1}^{leftlfloor frac{M}{d} ight floor} leftlfloor frac{M}{dy} ight floor$$

    我们只要求出(sumlimits_{i=1}^n leftlfloor frac{n}{i} ight floor)就行

    接下来是美滋滋的代码时间~~~

    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 50007
    #define int long long
    using namespace std;
    int T,n,m,cnt;
    int mu[N],sum[N],num[N],prime[N];
    bool isp[N];
    void Get()
    {
    	mu[1]=1;
    	for(int i=2;i<=N-7;++i)
    	{
    		if(!isp[i])
    		{
    			prime[++cnt]=i;
    			mu[i]=-1;
    		}
    		for(int j=1;j<=cnt&&(i*prime[j])<=N-7;++j)
    		{
    			isp[i*prime[j]]=1;
    			if(i%prime[j]==0)
    				break;
    			else
    				mu[i*prime[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<=N-7;++i)
    		sum[i]=sum[i-1]+mu[i];
    	for(int i=1;i<=N-7;++i)
    	{
    		int res=0;
    		for(int l=1,r;l<=i;l=r+1)
    		{
    			r=i/(i/l);
    			res+=(r-l+1)*(i/l);
    		}
    		num[i]=res;
    	}
    }
    signed main()
    {
    	Get();
    	scanf("%lld",&T);
    	while(T--)
    	{
    		scanf("%lld%lld",&n,&m);
    		int ans=0;
    		if(n>m)
    			swap(n,m);
    		for(int l=1,r;l<=n;l=r+1)
    		{
    			r=min(n/(n/l),m/(m/l));
    			ans+=(sum[r]-sum[l-1])*num[n/l]*num[m/l];
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    随感
    LIKE运算符
    数据库运行时的关键字先后顺序
    联表查询
    进程、线程、协程
    算法复杂度
    redis支持的数据类型
    面向对象编程和面向过程编程的区别总结
    判断对象的变量是否存在,isset和property_exists区别
    构造函数和析构函数
  • 原文地址:https://www.cnblogs.com/yexinqwq/p/11110078.html
Copyright © 2020-2023  润新知