版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lfhase/article/details/82562826
ACM-ICPC 2018 Xuzhou Online 徐州赛区网络赛(待更新)
D Easy Math
题目链接
题面:
(骗搜索)
Given a positive integers
, Mobius function
is defined as follows:
Given two integers mm, nn, please calculate
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
题目来源
ACM-ICPC 2018 徐州赛区网络预赛
题意:
计算
思路:
莫比乌斯反演+筛法。
设
代入莫比乌斯函数,得
变换一下,有
枚举n的所有因子,用筛法求
事实上,
所以再用杜教筛处理一下前缀和就好了,复杂度不会算(tao
AC代码:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#include <bitset>
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl;
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define REP(i,st,ed) for(int i=st;i<=ed;++i)
#define IREP(i,st,ed) for(int i=ed;i>=st;--i)
#define TCASE(T) cin>>T;while(T--)
const int MAXN = 2000005;
const ll MOD = 2333333 ;
const int INF = 1e9+7;
int _;
using namespace std;
ll N, M;
int rua(ll n)
{
int cnt = 0;
for(ll i = 2; i * i <= n; ++i)
{
if(n%i == 0)
{
n /= i;
++cnt;
if(n%i == 0) return 0;
}
}
if(n > 1) ++cnt;
return cnt&1?-1:1;
}
bool check[MAXN];
int prime[MAXN];
int mu[MAXN];
int summ[MAXN];
void Moblus()
{
memset(check,0,sizeof(check));
mu[1] = 1;
int tot = 0;
for(int i=2; i<MAXN; ++i)
{
if(!check[i])
{
prime[++tot] = i;
mu[i] = -1;
}
for(int j=1; j<=tot; ++j)
{
if(i*prime[j]>MAXN) break;
check[i*prime[j]] = 1;
if(i%prime[j]==0)
{
mu[i*prime[j]] = 0;
break;
}
else mu[i*prime[j]] = -mu[i];
}
}
summ[0] = 0;
for(int i=1; i<MAXN; ++i) summ[i] = summ[i-1]+mu[i];
}
ll get_mu(ll num)
{
if(num<MAXN) return 1LL*mu[num];
else return 1LL*rua(num);
}
struct p_my_map{
ll x;
int ans,next;
}p_e[MAXN+5];
int p_ans=0,p_num=0;
int p_head[MOD+5];
void p_ins(ll x,int sum)
{
int j=x%MOD;
p_e[++p_num]=(p_my_map){x,sum,p_head[j]};
p_head[j]=p_num;
}
int p_calc(ll n)
{
if(n<MAXN) return summ[n];
for(int i=p_head[n%MOD];i;i=p_e[i].next)
if(p_e[i].x==n)return p_e[i].ans;
int sum=1,q=sqrt(n);
for(int i=2;i<=q;i++)
sum-=p_calc(n/i);
q=n/(q+1);
for(int i=1;i<=q;i++)
sum-=(n/i-(n/(i+1)))*p_calc(i);
p_ins(n,sum);
return sum;
}
struct my_map
{
ll x, y;
int ans;
int next;
} e[MAXN+5];
int ans=0,num=0;
int head[MOD+5];
void ins(ll x,ll y,int sum)
{
int j=(x+y)%MOD;
e[++num]=(my_map)
{
x,sum,head[j]
};
head[j]=num;
}
ll calc(ll n, ll m)
{
if(m==0) return 0;
if(m==1) return get_mu(n);
if(n==1) return p_calc(m);
int tmp = get_mu(n);
if(!tmp) return 0;
for(int i=head[(n+m)%MOD]; i; i=e[i].next)
if(e[i].x==n&&e[i].y==m) return e[i].ans;
ll sum=0;
for(ll i=1;i*i<=n;++i)
{
if(!(i==1||n%i==0)) continue;
sum += get_mu(i)*calc(i,m/i);
if(n/i!=i) sum += get_mu(n/i)*calc(n/i,m/(n/i));
}
sum*=tmp;
ins(n,m,sum);
return sum;
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.in","w+",stdout);
Moblus();
scanf("%lld%lld",&M,&N);
int nnn = rua(N);
if(nnn==0) printf("%d\n",0);
else
{
num = p_num = 0;
printf("%lld\n",calc(N,M));
}
}