• luoguP3455 [POI2007]ZAP-Queries


    题意

    (f(n)=sumlimits_{i=1}^{a}sumlimits_{j=1}^{b}[gcd(i,j)==n],F(n)=sumlimits_{n|d}f(d))

    发现(F(n)=frac{a}{n}*frac{b}{n}),可以理解为对(a)以内的所有(k*n)都和(b)以内的(k*n)配对了一次。

    由莫比乌斯反演:
    (f(n)=sumlimits_{n|d}mu(frac{d}{n})F(d))
    (f(n)=sumlimits_{n|d}mu(frac{d}{n})frac{a}{d}*frac{b}{d})
    (t=frac{d}{n})
    (f(n)=sumlimits_{t=1}^{min(frac{a}{d},frac{b}{d})}mu(t)frac{a}{t*n}frac{b}{t*n})

    (ans=f(d))

    除法分块即可。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=50010;
    int T;
    int mu[maxn],sum[maxn];
    ll a,b,d;
    bool vis[maxn];
    vector<int>prime;
    inline void shai(int n)
    {
    	vis[1]=1;mu[1]=1;
    	for(int i=2;i<=n;i++)
    	{
    		if(!vis[i])prime.push_back(i),mu[i]=-1;
    		for(unsigned int j=0;j<prime.size()&&i*prime[j]<=n;j++)
    		{
    			vis[i*prime[j]]=1;
    			if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
    			mu[i*prime[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<=n;i++)sum[i]=sum[i-1]+mu[i];
    }
    inline ll solve(ll a,ll b,ll d)
    {
    	ll n=min(a/d,b/d),res=0;
    	for(int l=1,r;l<=n;l=r+1)
    	{
    		r=min(a/(a/l),b/(b/l));
    		res+=(a/(l*d))*(b/(l*d))*(sum[r]-sum[l-1]);
    	}
    	return res;
    }
    int main()
    {
    	shai(50000);
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%lld%lld%lld",&a,&b,&d);
    		printf("%lld
    ",solve(a,b,d));
    	}
    	return 0;
    }
    
  • 相关阅读:
    VC6 下 libpng 库的编译与初步使用
    Windows上编译libtiff
    ActiveX控件开发
    静态库和动态库的优缺点
    KStudio window上编译uclinux
    4. API之打印函数
    window消息机制二
    消息机制、子窗口和父窗口的消息传递
    window消息机制
    dll 显示调用
  • 原文地址:https://www.cnblogs.com/nofind/p/11939837.html
Copyright © 2020-2023  润新知