zoukankan      html  css  js  c++  java
  • P2522 [HAOI2011]Problem b 题解

    CSDN同步

    原题链接

    简要题意:

    [sum_{i=a}^b sum_{j=c}^d [gcd(i,j)==k] ]

    (T) 组询问.

    本题没有部分分,直接考虑一个式子:

    [sum_{i=1}^a sum_{j=1}^b [gcd(i,j)==k] ]

    [= sum_{i=1}^{lfloor frac{a}{k} floor} sum_{j=1}^{lfloor frac{b}{k} floor} [gcd(i,j)==1] ]

    [= sum_{i=1}^{lfloor frac{a}{k} floor} sum_{j=1}^{lfloor frac{b}{k} floor} sum_{d | gcd(i,j)} mu_d ]

    [= sum_{d=1}^{min(a,b)} mu_d lfloor frac{a}{dk} floor lfloor frac{b}{dk} floor ]

    上面每一步都是在用 莫比乌斯反演 的性质,不加解释。

    那么,我们只需要用 (O(n)) 的时间预处理 (mu),就可以用 整除分块(O(sqrt{min(a,b)})) 的时间内求解这样一个式子。

    那么,已知 (k),令:

    [f_{a,b} = sum_{i=1}^a sum_{j=1}^b [gcd(i,j)==k] ]

    则:

    [sum_{i=a}^b sum_{j=c}^d [gcd(i,j)==k] = f_{b,d} - f_{b,c-1} - f_{a-1,d} + f_{a-1,c-1} ]

    (可以稍微参考一下二维前缀和得出)

    所以我们以 (O(5 imes 10^4)) 预处理,(O(n sqrt{min(a,b)})) 询问解决了本题。

    时间复杂度:(O(a + nsqrt{a})).

    实际得分:(100pts).(需要适度卡常)

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N=1e6+1;
    
    inline ll read(){char ch=getchar(); ll f=1; while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	ll x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
    
    int prime[N],mu[N],sum[N];
    int cnt=0,k; bool h[N];
    
    inline void Euler(int n) {
    	mu[1]=1; for(register int i=2;i<=n;i++) {
    		if(!h[i]) mu[i]=-1,prime[++cnt]=i;
    		for(int j=1;j<=cnt && i*prime[j]<=n;j++) {
    			h[i*prime[j]]=1;
    			if(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];
    } //预处理 mu 的前缀和
    
    inline int min(int a,int b) {return a<b?a:b;}
    inline ll calc(int a,int b) {
    	ll ans=0;
    	for(register int i=1;i<=min(a,b);) {
    		int t=min(a/(a/i),b/(b/i));
    		ans+=1ll*(a/k/i)*(b/k/i)*(sum[t]-sum[i-1]);
    		i=t+1;
    	} return ans; //整除分块
    }
    
    int main() {
    	Euler(N-1); int T=read(); while(T--) {
    		int a=read(),b=read(),c=read(),d=read(); k=read();
    		printf("%lld
    ",calc(b,d)-calc(b,c-1)-calc(a-1,d)+calc(a-1,c-1));
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    HDU-5384
    UVALive 5099
    ZOJ-2753
    HUD-5379
    HDU-5360
    HDU-5351
    HDU-5335
    HDU-5317
    HDU-2487
    常用十六进制颜色对照表代码查询
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12818430.html
Copyright © 2011-2022 走看看