显然不是的,因为那个鸡性函数性质,是需要互质的。而p和i*n/p不一定互质鸭!但是我们先不管这个,待会再考虑这个。假设他俩互质了,一个质数的莫比乌斯函数值一定是-1,我们直接把-1提前,所以原式:
\[-\sum_{i=1}^{m}\mu{(i*\frac{n}{p})}\]
与索引无关的量可以提到和式前面(索引是指上式中的i)
这个二元组的边界条件,就是S(m,1)和S(0,n)。然而mn太大,所以边界直接杜教筛!
#include<cstdio>
#include<unordered_map>
using namespace std;
const int maxn = 1e7 + 10;
long long n, m;
int prime[maxn], min_p[maxn], mu[maxn], pre_mu[maxn];
bool no_prime[maxn];
int shai(int n)
{
int cnt = 0;
no_prime[1] = mu[1] = 1;
for (int i = 2; i <= n; i++)
{
if (!no_prime[i])
prime[++cnt] = i, mu[i] = -1, min_p[i] = i;
for (int j = 1; j <= cnt && i * prime[j] <= n; j++)
{
no_prime[prime[j] * i] = 1;
mu[prime[j] * i] = i % prime[j] == 0 ? 0 : -mu[i];
min_p[prime[j] * i] = prime[j];
if (i % prime[j] == 0) break;
}
}
for (int i = 1; i <= n; i++)
pre_mu[i] = pre_mu[i - 1] + mu[i];
return cnt;
}
unordered_map<int, int> rec_mu;
int cal(int n)//n的莫比乌斯函数前缀和
{
if (n <= maxn - 10) return pre_mu[n];
if (rec_mu[n]) return rec_mu[n];
int l = 2, r, ans = 1;
while (l <= n)
{
r = n / (n / l);
ans -= (r - l + 1) * cal(n / l);
l = r + 1;
}
return rec_mu[n] = ans;
}
long long S(long long m, long long n)
{
if (m == 0) return 0;
if (n == 1) return cal(m);
for (int i = 1; 1ll * prime[i] * prime[i] <= n; i++)
{
if (n % prime[i] == 0)
return -S(m, n / prime[i]) + S(m / prime[i], n);
}
return -S(m, n / n) + S(m / n, n);
}
void solve()
{
int cnt = shai(maxn - 10);
scanf("%lld%lld", &m, &n);
for (int i = 1; 1ll * prime[i] * prime[i] <= n; i++)
if (n % (1ll * prime[i] * prime[i]) == 0)
{
printf("0\n");
return;
}
printf("%lld\n", S(m, n));
}
int main()
{
freopen("Testin.txt", "r", stdin);
solve();
return 0;
}
ICPC 2018 南京网赛 Easy Math 递归式+杜教筛
原文:https://www.cnblogs.com/danzh/p/11398718.html