• 洛谷 P2522 [HAOI2011]Problem b


    洛谷 P2522 [HAOI2011]Problem b

    题意

    (n)组询问,每次给出(a,b,c,d,k),求(sumlimits_{x=a}^{b}sumlimits_{y=c}^{d}[gcd(x,y)=k])

    思路

    容斥原理+数论分块+莫比乌斯反演

    我做的莫比乌斯反演的第一道题= =

    (f(n,m)=sumlimits_{i=1}^{n}sumlimits_{j= 1}^{m}[gcd(i,j)=k])

    那么根据容斥原理,题目中的式子就转化成了(f(b,d)-f(b, c - 1) - f(a - 1,d) + f(a - 1, c - 1))

    所以我们接下来的问题就转化为了如何求(f)的值

    现在来化简(f)的值

    1. 容易得出原式等价于

    [sumlimits_{i = 1}^{lfloorfrac{n}{k} floor}sumlimits_{j = 1}^{lfloorfrac{m}{k} floor}[gcd(i,j) = 1] ]

    1. 因为(epsilon(n) =sumlimits_{d|n}mu(d)=[n=1]),由此可将原式化为

    [sumlimits_{i=1}^{lfloorfrac{n}{k} floor}sumlimits_{j=1}^{lfloorfrac{m}{k} floor}sumlimits_{d|gcd(i,j)}mu(d) ]

    1. 改变枚举对象并改变枚举顺序,先枚举(d),得

    [sumlimits_{d=1}^{min(n,m)}mu(d)sumlimits_{i=1}^{lfloorfrac{n}{k} floor}[d|i]sumlimits_{j=1}^{lfloorfrac{m}{k} floor}[d|j] ]

    也就是说当(d|i)(d|j)时,(d|gcd(i,j))

    1. 易得(1sim lfloorfrac{n}{k} floor)中一共有(lfloorfrac{n}{dk} floor)(d)的倍数,同理(1sim lfloorfrac{m}{k} floor)中一共有(lfloorfrac{m}{dk} floor)(d)的倍数,于是原式化为

    [sumlimits_{d=1}mu(d)lfloorfrac{n}{dk} floorlfloorfrac{m}{dk} floor ]

    此时已经可以(O(n))求解,但是过不了,因为有很多值相同的区间,所以可以用数论分块来做

    先预处理(mu),再用数论分块,复杂度(O(n+Tsqrt n))

    我的代码每次得分玄学,看评测机心情,建议自己写

    代码

    /*
    Author:loceaner
    */
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e6 + 11;
    const int B = 1e6 + 11;
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int n, a, b, c, d, k, cnt, p[A], mu[A], sum[A];
    bool vis[A];
    
    void getmu() {
    	int MAX = 50010;
    	mu[1] = 1;
    	for (int i = 2; i <= MAX; i++) {
    		if (!vis[i]) mu[i] = -1, p[++cnt] = i;
    		for (int j = 1; j <= cnt && i * p[j] <= MAX; j++) {
    			vis[i * p[j]] = true;
    			if (i % p[j] == 0) break;
    			mu[i * p[j]] -= mu[i];
    		}
    	}
    	for (int i = 1; i <= MAX; i++) sum[i] = sum[i - 1] + mu[i];
    }
    
    int work(int x, int y) {
    	int ans = 0ll;
    	int max = min(x, y);
    	for (int l = 1, r; l <= max; l = r + 1) {
    		r = min(x / (x / l), y / (y / l));
    		ans += (1ll * x / (l * k)) * (1ll * y / (l * k)) * 1ll * (sum[r] - sum[l - 1]); 
    	}
    	return ans;
    }
    
    void solve() {
    	a = read(), b = read(), c = read(), d = read(), k = read();
    	cout << work(b, d) - work(a - 1, d) - work(b, c - 1) + work(a - 1, c - 1) << '
    ';
    }
    
    signed main() {
    	getmu();
    	int T = read();
    	while (T--) solve();
    	return 0;
    }
    
    
  • 相关阅读:
    封装/接口/抽象类
    继承
    浅谈面向对象
    MySQL---Mybatis 批处理(增,改,删)
    dashboard安装
    K8S--------常用命令
    K8S------概述
    Java实现 MD5加盐加密 和 MD5和SHA-1混合加盐加密
    使用FastJson对JSON字符串、JSON对象及JavaBean之间的相互转换
    SpringCloud---FeignClient处理请求超时问题
  • 原文地址:https://www.cnblogs.com/loceaner/p/12717450.html
Copyright © 2020-2023  润新知