• bzoj2301 [HAOI2011]Problem b【莫比乌斯反演 分块】


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2301

    很好的一道题。首先把每个询问转化为4个子询问,最后的结果就是这四个子询问的记过加加减减,类似二维前缀和。那么问题转化为在1 <= x <= lmtx, 1 <= y <= lmty时gcd(x, y) == k的对数,这个问题在转化一下,转化成1 <= x <= lmtx / k,1 <= y <= lmty / k时x与y互质的对数。莫比乌斯反演一下,就有了,但是会TLE,所以需要分块优化。

    其它博客讲得很清楚了,程序精华在15~16行。

    #include <cstdio>
    #include <algorithm>
     
    const int maxn = 50005;
     
    int n, a, b, c, d, k, mu[maxn] = {0, 1}, prime[maxn], tot, s[maxn];
    char book[maxn];
     
    inline long long slove(int lmtx, int lmty) {
    	lmtx /= k;
    	lmty /= k;
        int lmt = std::min(lmtx, lmty), last;
        long long rt = 0;
        for (int i = 1; i <= lmt; i = last + 1) {
        	last = std::min(lmtx / (lmtx / i), lmty / (lmty / i));
        	rt += (long long)(lmtx / i) * (lmty / i) * (s[last] - s[i - 1]);
    	}
        return rt;
    }
     
    int main(void) {
        scanf("%d", &n);
        for (int i = 2; i < maxn; ++i) {
            if (!book[i]) {
                prime[tot++] = i;
                mu[i] = -1;
            }
            for (int j = 0; j < tot; ++j) {
                if (i * prime[j] > maxn) {
                    break;
                }
                book[i * prime[j]] = 1;
                if (i % prime[j] == 0) {
                    break;
                }
                else {
                    mu[i * prime[j]] = -mu[i];
                }
            }
        }
        for (int i = 1; i < maxn; ++i) {
        	s[i] = s[i - 1] + mu[i];
    	}
        while (n--) {
            scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
            printf("%lld
    ", slove(b, d) - slove(a - 1, d) - slove(b, c - 1) + slove(a - 1, c - 1));
        }
        return 0;
    }
    

      

  • 相关阅读:
    opacity兼容性以及存在问题处理
    删除节点方法要注意的区别
    java基础-常见面试题(一)
    第04次作业-树
    第03次作业-栈和队列
    第02次作业-线性表
    Data_Structure-绪论作业
    C语言第二次实验报告
    C语言第一实验报告
    mysql 查询优化
  • 原文地址:https://www.cnblogs.com/ciao-sora/p/6371980.html
Copyright © 2020-2023  润新知