• BZOJ 2818 GCD 【欧拉函数 || 莫比乌斯反演】


    传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=2818

    2818: Gcd

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 9236  Solved: 4126
    [Submit][Status][Discuss]

    Description

    给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
    数对(x,y)有多少对.

    Input

    一个整数N

    Output

    如题

    Sample Input

    4

    Sample Output

    4

    HINT


    对于样例(2,2),(2,4),(3,3),(4,2)


    1<=N<=10^7

    解题思路:

    老套路:GCD( x, y )  = p 转换成 GCD( x/p, y/p ) = 1;

    那么按照原来的配方,我们需要枚举 x/p 或者 y/p 其中一个数,然后另外一个数的总数通过欧拉函数求得。

    假设选择枚举 y/p ,那么还需要暴力一遍枚举素数。(一开始就是直接暴力。。。)

    然而O( n ) 内可以同时筛出素数和欧拉函数值:https://oi.abcdabcd987.com/sieve-prime-in-linear-time/

    同时记录一下欧拉函数前缀和 sum[k] ,根据上面的转换我们可知:

    如果给出 x <= y ,则直接枚举素数枚举y,然后欧拉函数求所有方案数即可;

    但是这里没有明确表明 x 和 y 的大小关系, 但是我们还是只求一半 即 (默认 x <= y)的情况,然后这个答案乘以 2 就是 (y <= x)的情况了,需要去一下重(即 x = y = 1)的情况。 

    枚举 素数 p ,求 [ 1,  N/p ] 中互质的数对的总数, 即 2*sum[ N/p ]  - 1;

    AC code:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 const int MAXN = 1e7+10;
     5 bool com[MAXN];
     6 int primes, prime[MAXN], phi[MAXN];
     7 LL sum[MAXN];
     8 
     9 void get_phi(int n){
    10     phi[1] = 1;
    11     for (int i = 2; i <= n; ++i)
    12     {
    13       if (!com[i])
    14       {
    15         prime[primes++] = i;
    16         phi[i] = i-1;
    17       }
    18       for (int j = 0; j < primes && i*prime[j] <= n; ++j)
    19       {
    20         com[i*prime[j]] = true;
    21         if (i % prime[j])
    22           phi[i*prime[j]] = phi[i]*(prime[j]-1);
    23         else
    24           { phi[i*prime[j]] = phi[i]*prime[j]; break; }
    25       }
    26       //sum[i] = sum[i-1]+phi[i];
    27     }
    28 }
    29 int main()
    30 {
    31     int N;
    32     scanf("%d", &N);
    33     get_phi(N);
    34     sum[1] = 1;
    35     for(int i = 2; i <= N/2; i++){
    36         sum[i] = sum[i-1]+phi[i];
    37 //        phi[i] = phi[i-1]+phi[i];
    38     }
    39 //    printf("%d
    ", phi[1]);
    40     LL ans = 0;
    41     for(int i = 0; i < primes; i++){
    42         ans = ans + (sum[N/prime[i]]*2-1);
    43     }
    44     printf("%lld
    ", ans);
    45 
    46     return 0;
    47 }
  • 相关阅读:
    HTML的基础
    样式表
    页面布局
    for 循环
    函数
    数组
    样式属性
    css选择器参考手册
    样式表格及选择器
    表单
  • 原文地址:https://www.cnblogs.com/ymzjj/p/10357199.html
Copyright © 2020-2023  润新知