zoukankan      html  css  js  c++  java
  • [BZOJ1101][POI2007]Zap

    1101: [POI2007]Zap

    Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2732  Solved: 1164 [Submit][Status][Discuss]

    Description

      FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a ,y<=b,并且gcd(x,y)=d。作为FGD的同学,FGD希望得到你的帮助。

    Input

      第一行包含一个正整数n,表示一共有n组询问。(1<=n<= 50000)接下来n行,每行表示一个询问,每行三个 正整数,分别为a,b,d。(1<=d<=a,b<=50000)

    Output

      对于每组询问,输出到输出文件zap.out一个正整数,表示满足条件的整数对数。

    Sample Input

    2
    4 5 2
    6 4 3

    Sample Output

    3
    2
    //对于第一组询问,满足条件的整数对有(2,2),(2,4),(4,2)。对于第二组询问,满足条件的整数对有(
    6,3),(3,3)。
     
    不妨设$a'=lfloorfrac{a}{d} floor,b'=lfloorfrac{b}{d} floor,a'le b'$
    那么题目要求的是$sum_{xle a',yle b'}left[gcdleft(x,y ight)=1 ight]$
    设$f(n)$表示$sum_{xle a',yle b'}left[gcdleft(x,y ight)=n ight]$
    和$g(n)$表示$sum_{xle a',yle b'}left[nmid gcdleft(x,y ight) ight]$
    那么答案就是$f(1)$
    又显然$g(n)=lfloorfrac{a'}{n} floorlfloorfrac{b'}{n} floor$
    并且满足关系式$g(n)=sum_{dle a',nmid d}f(d)$
    反演得$f(n)=sum_{dle a', nmid d}muleft(frac{d}{n} ight)g(d)=sum_{dle a', nmid d}muleft(frac{d}{n} ight)lfloorfrac{a'}{d} floorlfloorfrac{b'}{d} floor$
    将$n=1$代入得到$f(1)=sum_{dle a'}muleft(d ight)lfloorfrac{a'}{d} floorlfloorfrac{b'}{d} floor$
    但这样单次询问是$Oleft(n ight)$的,仍需要优化
    观察式(ti)子(jie)可以发现
    后面两个向下取整在一段区间内不会变,如果我们处理出了$mu$的前缀和就可以一段一段的求解
    又因为只有$Oleft(sqrt{n} ight)$段
    所以在$Oleft(n ight)$的预处理后单次询问是$Oleft(sqrt{n} ight)$的
    所以总时间复杂度为$Oleft(nsqrt{n} ight)$
    #pragma GCC optimize("O2")
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    char buf[10000000], *ptr = buf - 1;
    inline int readint(){
        int n = 0;
        while(*++ptr < '0' || *ptr > '9');
        while(*ptr <= '9' && *ptr >= '0') n = (n << 1) + (n << 3) + (*ptr++ & 15);
        return n;
    }
    const int maxn = 50000 + 10;
    bool mark[maxn] = {false};
    int mu[maxn], sum[maxn];
    int pri[maxn], prn = 0;
    void shai(){
        mu[1] = 1;
        for(int i = 2; i <= 50000; i++){
            if(!mark[i]){
                pri[++prn] = i;
                mu[i] = -1;
            }
            for(int j = 1; j <= prn && pri[j] * i <= 50000; j++){
                mark[i * pri[j]] = true;
                if(i % pri[j] == 0){
                    mu[i * pri[j]] = 0;
                    break;
                }
                else mu[i * pri[j]] = -mu[i];
            }
        }
        sum[0] = 0;
        for(int i = 1; i <= 50000; i++)
            sum[i] = sum[i - 1] + mu[i];
    }
    int a, b, d;
    inline void work(){
        a = readint();
        b = readint();
        d = readint();
        a /= d;
        b /= d;
        if(a > b) swap(a, b);
        int ans = 0, pos;
        for(int i = 1; i <= a; i = pos + 1){
            pos = min(a / (a / i), b / (b / i));
            ans += (sum[pos] - sum[i - 1]) * (a / i) * (b / i);
        }
        printf("%d
    ", ans);
    }
    int main(){
        fread(buf, sizeof(char), sizeof(buf), stdin);
        shai();
        int n = readint();
        while(n--) work();
        return 0;
    }
  • 相关阅读:
    mysql8.0.21下载安装详细教程
    ORDER BY 高级用法之CASE WHEN继续研究
    前端实用在线小工具推荐
    从nodejs的AES加密解密之后文件大小不一致的问题谈谈AES加密中的补位
    纯前端如何实现多语言切换
    [React] React Virtual
    [Kotlin] Compare Functional Programming in Java and Kotlin
    [Kotlin] Catch Error in Java
    [Angular] Saving draft form into Cookies
    [Angular] Data Resolver
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/7630019.html
Copyright © 2011-2022 走看看