传送门
有毒的数据范围。
直接容斥+高精度不虚。
#include<cstring>
#include<cmath>
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#define ll long long
#define mo 1000000000
using namespace std;
struct num{
ll a[1005];
void clear(){memset(a,0,sizeof(a));}
void print(){
printf("%lld",a[a[0]]);
for (int i=a[0]-1;i>0;i--) printf("%09lld",a[i]);
printf("\n");
}
num operator * (const num b) const{
num c;
c.clear();
for (int i=1;i<=a[0];i++){
ll x=0;
for (int j=1;j<=b.a[0];j++){
x+=c.a[j+i-1]+a[i]*b.a[j];
c.a[j+i-1]=x%mo;
x/=mo;
}
c.a[i+b.a[0]]=x;
}
c.a[0]=a[0]+b.a[0];
while (!c.a[c.a[0]]&&c.a[0]) c.a[0]--;
return c;
}
num operator + (const num b) const{
num c;
c.clear();
c.a[0]=max(a[0],b.a[0]);
for (int i=1;i<=c.a[0];i++) c.a[i]=a[i]+b.a[i];
for (int i=1;i<=c.a[0];i++){
c.a[i+1]+=c.a[i]/mo;
c.a[i]%=mo;
}
c.a[0]++;
while (!c.a[c.a[0]]&&c.a[0]) c.a[0]--;
return c;
}
num operator - (const num b) const{
num c;
c.clear();
c.a[0]=a[0];
for (int i=1;i<=c.a[0];i++) c.a[i]=a[i]-b.a[i];
for (int i=1;i<=c.a[0];i++)
if (c.a[i]<0){
c.a[i+1]--;
c.a[i]+=mo;
}
while (!c.a[c.a[0]]&&c.a[0]) c.a[0]--;
return c;
}
}ans,s,jia,jian;
int n,m,tot,tmp,sum,p,a[30];
inline void pow(int x,int y,num &p){
num b;
b.clear();
p.clear();
b.a[0]=p.a[0]=p.a[1]=1;
b.a[1]=x;
while (y){
if (y%2) p=p*b;
b=b*b;
y/=2;
}
}
int main(){
scanf("%d%d",&n,&m);
pow(m,n,ans);
tot=0;
tmp=m;
for (int i=2;i*i<=tmp;i++)
if (tmp%i==0){
a[++tot]=i;
while (tmp%i==0) tmp/=i;
}
if (tmp!=1) a[++tot]=tmp;
for (int i=1;i<(1<<tot);i++){
sum=1;
p=0;
for (int j=1;j<=tot;j++)
if (i&(1<<(j-1))) sum*=a[j],p++;
pow(m/sum,n,s);
if (p%2) jian=jian+s;
else jia=jia+s;
}
ans=ans+jia;
ans=ans-jian;
ans.print();
}