先放一个问答区的图
求。
考虑莫比乌斯函数的定义,当n = k*p*p (p > 1)时,。
又考虑到莫比乌斯函数作为积性函数的性质,则有:。
由容斥原理:
令: ,则:。
先预处理n的质因子,就可以加速的计算,递归地进行处理。
考虑处理到边界时,n = 1即为求。预处理以内的数,其余部分用杜教筛来进行处理。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll maxn = 1000050;
const ll INF = (1LL << 62) - 1;
const ll mod = 1000000007;
int no, num;
bool ispri[maxn];
ll pri[maxn], p[maxn], prif[25];
ll mu[maxn], summu[maxn];
struct node
{
ll x, y;
node(ll _x, ll _y):x(_x), y(_y){}
bool operator < (node a)const
{
if(x == a.x)return y < a.y;
return x < a.x;
}
};
map<node, ll>mp;
map<ll, ll>dmap;
void init()
{
mp.clear(), dmap.clear();
no = 0;
memset(ispri, -1, sizeof(ispri));
memset(mu, 0, sizeof(mu));
mu[1] = 1;
for(ll i = 2;i < maxn;i++)
{
if(ispri[i] != 0) pri[no++] = i, mu[i] = -1;
for(int j = 0;j < no && i*pri[j] < maxn;j++)
{
ispri[i*pri[j]] = false;
if(i % pri[j] == 0) break;
mu[i*pri[j]] = -mu[i];
}
}
summu[1] = 1;
for(int i = 2; i < maxn;i++)
summu[i] = summu[i-1] + mu[i];
}
bool getpri(ll n)
{
num = 0;
for(int i = 0;i < no && pri[i]*pri[i] <= n;i++)
{
if(n % pri[i] == 0)
{
if((n/pri[i]) % pri[i] == 0) return false;
p[num++] = pri[i];
while(n % pri[i] == 0) n /= pri[i];
}
}
if(n != 1) p[num++] = n;
return true;
}
ll sol(ll n)
{
if(n < maxn) return summu[n];
if(dmap.count(n)) return dmap[n];
ll ans = 1, p = 0;
for(ll i = 2;i <= n;i = p + 1)
{
p = n/(n/i);
ans -= sol(n/i)*(p-i+1);
}
return dmap[n] = ans;
}
ll cal(ll m, ll n)
{
node cnm(m, n);
if(mp.count(cnm)) return mp[cnm];
if(n == 1) return sol(m);
ll prif[25];
ll ans = 0, numf = 0;
for(int i = 0;i < num;i++)
{
if(n % p[i] == 0)
prif[numf++] = p[i];
}
for(int i = 0;i < (1<<numf);i++)
{
ll d = 1, mud = 1;
for(int j = 0;j < numf;j++)
{
if((i>>j) & 1)
{
d *= prif[j];
mud = -mud;
}
}
if(m >= d) ans += mud*cal(m/d, d);
}
return mp[cnm] = numf%2 ? -ans : ans;
}
int main()
{
init();
ll m, n;
scanf("%lld%lld", &m, &n);
if(getpri(n)) printf("%lld\n", cal(m, n));
else printf("0\n");
return 0;
}