NOIP模拟赛 太阳神

太阳神拉很喜欢最小公倍数,有一天他想到了一个关于最小公倍
数的题目。
求满足如下条件的数对(a,b)对数:a,b 均为正整数且a,b<=n 而
lcm(a,b)>n。其中的lcm 当然表示最小公倍数。答案对1,000,000,007
取模
n<=10000000000

换个方向,求lcm(a,b)<=n的对数。
设gcd(a,b) = d

sigma([a/d * b/d * d <= n && gcd(a/d,b/d)=1])
=sigma(mu[c] * sigma([a/d * b/d * d <= n && c|gcd(a/d,b/d)]))
=sigma(mu[c] * sigma([a/d/c * b/d/c * d<=n]))
然后你会惊奇的发现a/d和b/d和d这3个数已经只有积小于n/c/c这唯一的一层关系了,
然后枚举这3个数中最小的,第二小的,算出最大的数的范围,然后就可以计算贡献了。
枚举3个数是O(n2/3)的,外层枚举c,c>1时的复杂度其实是高阶小量,不用管,总复杂度O(n2/3)。
AC Code:

//%%%zjx dalao
#include
#include
#include
#include
#define maxn 100005
#define mod 1000000007
#define LL long long
using namespace std;
LL n,ans;
int mu[maxn],pr[maxn],cnt_pr,vis[maxn];
int main()
{
	scanf("%lld",&n);
	mu[1] = 1;
	int lim = int(sqrt(n)+0.5);
	for(int i=2;i<=lim;i++)
	{
		if(!vis[i]) pr[cnt_pr++] = i , mu[i] = -1;
		for(int j=0;j

你可能感兴趣的:(数论,枚举,奇巧淫技,容斥)