2018ACM-ICPC徐州赛区网络赛: D. Easy Math(Min_25筛)

 

D. Easy Math

Given a positive integers nn , Mobius function \mu(n)μ(n) is defined as follows:

\displaystyle \mu(n) = \begin{cases} 1 &n = 1 \\ (-1)^k & n = p_1p_2\cdots p_k \\ 0 &other \end{cases}μ(n)=⎩⎪⎨⎪⎧​1(−1)k0​n=1n=p1​p2​⋯pk​other​

p_i (i = 1, 2, \cdots, k)pi​(i=1,2,⋯,k) are different prime numbers.

Given two integers mm, nn, please calculate \sum_{i = 1}^{m} \mu(in)∑i=1m​μ(in).

Input

One line includes two integers m (1 \le m \le 2e9)m(1≤m≤2e9), n (1 \le n \le 1e12)n(1≤n≤1e12) .

Output

One line includes the answer .

样例输入

2 2

样例输出

-1

 

题意:

已知,求

 

思路:

不需要递归,更不需要容斥!直接将min_25修改一下即可,20ms

Min_25筛:https://blog.csdn.net/Jaihk662/article/details/82024131

可以分析出这题的递推公式就是:\small -\small S_f(m,y)=T+\sum_{i=y}^tS(\left \lfloor \frac{m}{p_i} \right \rfloor,y+1)

答案就是\small (S_f(n,1)+1)*\mu (n)

其中T表示大于等于第y个质数且小于m且不是n的因子的质数个数,右边的求和中\small p_i不能为n的因子

复杂度约为O(\small \sqrt{n})

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
LL cnt, Cnt, id[1000005], B, m, H[1000005], jud[1000005], Ans, n, w[1000005], pri[1000005], Pri[100005];
bool flag[1000005];
void Primeset(LL n)
{
	LL i, j;
	for(i=2;i<=n;i++)
	{
		if(flag[i]==0)
			pri[++cnt] = i;
		for(j=1;j<=cnt&&i*pri[j]<=n;j++)
		{
			flag[i*pri[j]] = 1;
			if(i%pri[j]==0)
				break;
		}
	}
}
LL F(LL x, LL y)
{
	LL i, k, ans;
	if(x<=1 || pri[y]>x)
		return 0;
	if(x>B)
		k = n/x;
	if(x<=B)
		k = id[x];
	ans = (y-1)-H[k];
	for(i=1;i<=Cnt;i++)
	{
		if(Pri[i]>pri[y-1] && Pri[i]<=w[k])
			ans++;
	}
	for(i=y;i<=cnt&&(LL)pri[i]*pri[i]<=x;i++)
	{
		if(jud[i]==0)
			ans = ans-F(x/pri[i], i+1);
	}
	return ans;
}
 
int main(void)
{
	LL i, j, k, P, last, sum;
	scanf("%lld%lld", &n, &P);
	B = sqrt(n), Primeset(1000002);
	sum = 0;
	for(i=1;i<=cnt&&pri[i]*pri[i]<=P;i++)
	{
		if(P%(pri[i]*pri[i])==0)
		{
			printf("0\n");
			return 0;
		}
		if(P%pri[i]==0)
		{
			jud[i] = 1;
			Pri[++Cnt] = pri[i], sum++;
			P /= pri[i];
		}
	}
	if(P!=1)
	{
		Pri[++Cnt] = P, sum++;
		for(i=1;i<=cnt;i++)
		{
			if(pri[i]==P)
				jud[i] = 1;
		}
	}
	for(i=1;i<=n;i=last+1)
	{
		w[++m] = n/i;
		H[m] = w[m]-1;
		last = n/(n/i);
		if(n/i<=B)
			id[n/i] = m;
	}
	for(j=1;j<=cnt;j++)
	{
		for(i=1;i<=m&&pri[j]*pri[j]<=w[i];i++)
		{
			if(w[i]/pri[j]<=B)
				k = id[w[i]/pri[j]];
			else
				k = n/(w[i]/pri[j]);
			H[i] = H[i]-(H[k]-(j-1));
		}
	}
	Ans = F(n, 1)+1;
	if(Cnt%2==1)
		Ans *= -1;
	printf("%lld\n", Ans);
	return 0;
}

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM-ICPC(国际大学生程序设计竞)是一项面向大学生的计算机编程竞,涉及算法和数据结构等领域。在比中,选手需要解决一系列编程问题,使用合适的算法和数据结构来实现正确和高效的解决方案。 对于整理ACM-ICPC模板,以下是一些建议: 1. 了解比要求:首先,你需要了解ACM-ICPC的具体要求和规则。这包括了解比所涉及的算法和数据结构,以及题目的类型和难度等。 2. 收集资料:收集与ACM-ICPC相关的资料,包括经典算法和数据结构的实现代码、常见问题的解题思路等。可以参考教材、博客、论文等资源。 3. 整理模板:将收集到的资料整理成模板。可以按照算法和数据结构的分类进行整理,例如排序算法、图算法、字符串算法等。对每个模板,添加必要的注释和示例代码,以便理解和使用。 4. 测试代码:对每个模板编写测试代码,确保它们的正确性和可靠性。可以使用已知的测试用例或自行设计测试用例。 5. 更新与扩充:定期更新和扩充模板,以适应ACM-ICPC中新出现的算法和数据结构。同时,根据自己的经验和理解,对模板进行优化和改进。 6. 练习和复习:在比之前,利用整理好的模板进行练习和复习。尝试解决一些经典问题,使用模板中的算法和数据结构进行实现,并进行优化。 希望这些建议对你整理ACM-ICPC模板有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值