zoukankan      html  css  js  c++  java
  • luogu2658 GCD(莫比乌斯反演/欧拉函数)

    link

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

    1<=N<=10^7

    (1)莫比乌斯反演法

    发现就是YY的GCD,左转YY的GCD粘过来就行

    代码太丑,没开O2 TLE5个点

    #include <cstdio>
    #include <functional>
    using namespace std;
    
    const int fuck = 10000000;
    int prime[10000010], tot;
    bool vis[10000010];
    int mu[10000010], sum[10000010];
    
    int main()
    {
    	mu[1] = 1;
    	for (int i = 2; i <= fuck; i++)
    	{
    		if (vis[i] == false) prime[++tot] = i, mu[i] = -1;
    		for (int j = 1; j <= tot && i * prime[j] <= fuck; j++)
    		{
    			vis[i * prime[j]] = true;
    			if (i % prime[j] == 0) break;
    			mu[i * prime[j]] = -mu[i];
    		}
    	}
    	for (int i = 1; i <= tot; i++)
    		for (int j = 1; j * prime[i] <= fuck; j++)
    			sum[j * prime[i]] += mu[j];
    	for (int i = 1; i <= fuck; i++)
    		sum[i] += sum[i - 1];
    	// int t; scanf("%d", &t);
    	// while (t --> 0)
    	// {
    		int n, m;
    		long long ans = 0; //别忘了初始化。。。
    		scanf("%d", &n), m = n;
    		if (n > m) {int t = m; m = n; n = t; }
    		for (int i = 1, j; i <= n; i = j + 1)
    		{
    			j = min(n / (n / i), m / (m / i));
    			ans += (sum[j] - sum[i - 1]) * (long long)(n / i) * (m / i);
    		}
    		printf("%lld
    ", ans);
    	// }
    	return 0;
    }
    

    (2)欧拉函数法

    对于一个(p)我们发现(sum_{i=1}^nsum_{j=1}^n[gcd(i,j)=p])即为(sum_{i=1}^{n/p}sum_{j=1}^{n/p}[gcd(i,j)=1])

    左转SDOI仪仗队那题,发现这个式子就是(2varphi(lfloorfrac n p floor)+1)

    线性筛就行

    (一个月前的代码

    #include <bits/stdc++.h>
    using namespace std;
    
    int vis[10000010];
    long long phi[10000010];
    int prime[1000010], tot, n;
    
    int main()
    {
        cin >> n;
        phi[1] = 1;
        for (int i = 2; i <= n; i++)
        {
            if (vis[i] == 0)
                prime[++tot] = i, phi[i] = i - 1;
            for (int j = 1; j <= tot && i * prime[j] <= n; j++)
            {
                vis[i * prime[j]] = true;
                if (i % prime[j] == 0)
                {
                    phi[i * prime[j]] = phi[i] * prime[j];
                    break;
                }
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
            vis[i] ^= 1;
            vis[i] += vis[i - 1];
            phi[i] += phi[i - 1];
        }
        long long ans = 0;
        for (int i = 1; i <= tot; i++)
            ans += 2 *  phi[n / prime[i]] - 1;
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    git常用指令 github版本回退 reset
    三门问题 概率论
    如何高效的学习高等数学
    数据库6 关系代数(relational algebra) 函数依赖(functional dependency)
    数据库5 索引 动态哈希(Dynamic Hashing)
    数据库4 3层结构(Three Level Architecture) DBA DML DDL DCL DQL
    梦想开始的地方
    java String字符串转对象实体类
    java 生成图片验证码
    java 对象之间相同属性进行赋值
  • 原文地址:https://www.cnblogs.com/oier/p/10295781.html
Copyright © 2011-2022 走看看