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

 

题意:

已知2018ACM-ICPC徐州赛区网络赛: D. Easy Math(Min_25筛)_第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
#include
#include
#include
#include
#include
#include
#include
#include
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;
}

 

你可能感兴趣的:(#,数论)