首页 > 编程语言 >算法提高课

算法提高课

时间:2022-12-07 09:11:31浏览次数:40  
标签:frac int 提高 ++ 算法 mobius primes 我们

达达正在破解一段密码,他需要回答很多类似的问题:

对于给定的整数 a,ba,b 和 dd,有多少正整数对 x,yx,y,满足 x≤a,y≤bx≤a,y≤b,并且 gcd(x,y)=dgcd(x,y)=d。

作为达达的同学,达达希望得到你的帮助。

输入格式

第一行包含一个正整数 nn,表示一共有 nn 组询问。

接下来 nn 行,每行表示一个询问,每行三个正整数,分别为 a,b,da,b,d。

输出格式

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

数据范围

1≤n≤500001≤n≤50000,
1≤d≤a,b≤500001≤d≤a,b≤50000

输入样例:

2
4 5 2
6 4 3

输出样例:

3
2

提示:gcd(x,y)gcd(x,y) 返回 x,yx,y 的最大公约数。

核心思路:首先我们需要知道莫比乌斯函数的相关定义:

我们对于原式子化简可得:x'<=\(\frac{a}{d}\),y‘<=\(\frac{b}{d}\),gcd(x',y')=1;所以整个问题转换为了求x'和y'互质的对数,在一定的范围内。这里可以用到容斥原理了,也就是合法的对数=总对数-不合法的对数。

总对数很好求:我们令a'=\(\frac{a}{d}\),b'=\(\frac{b}{d}\),所以总对数就是a'b';

那不合法的对数我们怎么转换为呢,我们就分情况:找出一个公共的质因子,找出两个公共的质因子......

使用数学符号就可以表示为:\(\frac{a'}{2}*\frac{b'}{2}\),\(\frac{a'}{6}\frac{b'}{6}\)......。然后我们需要注意下,我们使用容斥原理是需要找集合,所以我们可以吧把只有一个质因子的定义为\(S_1\),有两个定义为\(S_2\),以此类推。

所以我们使用容斥原理的总表示就是:

其实我们会发现这个是正好符合我们莫比乌斯函数的定义的。因为我们规定只要有一个质因子就是-1(次数不可以大于1),两个就是1,以此类推。就是\((-1)^k\).
接下来就是数论分块的思想了。不记得一定要去看博客,顺便看下莫比乌斯反演的博客,加深印象.
因为我们的\(\frac{a'}{i}\)和\(\frac{b'}{i}\)在一定的区间内这个函数值是不会变的,所以我们需要求一下前缀和u(x)函数的。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 6e5 + 10;
int primes[N], st[N];
int mobius[N],sum[N];
int cnt;
void Init()
{
    mobius[1]=1;
	for (int i = 2;i < N;i++)
	{
		if (!st[i])
		{
			primes[cnt++] = i;
			mobius[i] = -1;
		}
		for (int j = 0;primes[j] * i < N;j++)
		{
			int t = primes[j] * i;
			st[t] = 1;
			if (i % primes[j] == 0)//说明至少含有两个primes[j]
			{
				mobius[t] = 0;
				break;
			}
			mobius[t] = -mobius[i];
		}
	}
	for (int i = 1;i < N;i++)
		sum[i] = sum[i - 1] + mobius[i];
}
int main()
{
	Init();
	int T;
	cin >> T;
	while (T--)
	{
		LL res = 0;
		int a, b, d;
		cin >> a >> b >> d;
		a /= d;
		b /= d;
		int n = min(a, b);//这个和我们的定义有关可以看下那个推导的公式
		for (int l = 1, r;l <= n;l = r + 1)
		{
			r = min(n, min(a / (a / l), b / (b / l)));//这里有人差不多,反正可以理解为取交集
			res += (sum[r] - sum[l - 1]) * (LL)(a / l) * (b / l);
		}
		cout << res << endl;
	}
}

标签:frac,int,提高,++,算法,mobius,primes,我们
From: https://www.cnblogs.com/xyh-hnust666/p/16962063.html

相关文章

  • 代码随想录算法训练营Day16| 104. 二叉树的最大深度、559.n叉树的最大深度、111. 二叉
    代码随想录算法训练营Day16|104.二叉树的最大深度、559.n叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数104.二叉树的最大深度104.二叉树的最大......
  • 看起来简单实际上却很牛的KMP算法:LeetCode572-另一棵树的子树
    题目描述给定两个非空二叉树s和t,检验s中是否包含和t具有相同结构和节点值的子树。s的一个子树包括s的一个节点和这个节点的所有子孙。s也可以看做它自身的一棵......
  • 算法-哈希表、集合、映射
    1、两数之和(简单)题目地址:https://leetcode.cn/problems/two-sum/description/给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的......
  • 算法第二章
    1、习题     2、归并排序    3、分治法概述            4、快速排序             ......
  • 算法进阶课
    对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y)=k,gcd(x,y)函数为x和y的最大公约数。输入格式第一行一个整数n。接下来n行每行......
  • BFPRT算法(TOP-K问题)
    一:背景介绍在一大堆数中求其前k大或前k小的问题,简称TOP-K问题。而目前解决TOP-K问题最有效的算法即是BFPRT算法,其又称为中位数的中位数算法,该算法由Blum、Floyd、Pratt、Riv......
  • 算法复杂度分析概要
    一:渐近符号1.1符号的辨析1.1.1符号OO,读作“大O”,非正式来说,O(g(n))是增长次数小于等于g(n)及其常数倍(n趋向于无穷大)的函数集合。  定义如果函数f(n)包含在O(g(n))中,......
  • 面试算法题
    小球高处落下回弹运动距离"""一个小球从100m高度落下,每次弹回原高度一半.计算:--总共弹起多少次?(最小弹起高度0.01m)13次--全过程总共移动......
  • Vue的keep-alive、虚拟DOM的作用、diff算法
    一、keep-alive作用:keep-alive标签是vue的内置标签,可在组件切换过程中将状态保留在内存中,防止DOM重复渲染。标签属性:include:符合条件的组件会被缓存,exclude:符合条件的组......
  • 朴素贝叶斯算法
    一,朴素贝叶斯算法理论基础朴素贝叶斯算法是基于贝叶斯定理与特征条件独立假设的分类方法。对于给定的训练集,首先基于特征条件独立假设学习输入输出的联合概率分布(朴素贝叶......