文章目录
题目链接:
http://poj.org/problem?id=1091
貌似真的要用高精度,这数据范围真的有问题,随便想个数据都能装不下,long long 能过应该是数据有点水~反正学到这个方法就是了 ~
比如: 8 100000000
要求的就是前面可以任意变的N个数以及最后一个数M的gcd等于1
所以就又是求的他的反面,就是用总的个数减去gcd=2的,减去gcd=3的…
那怎么求呢?比如gcd=d的,那么每个位置就有
M
d
\frac{M}{d}
dM个,总共N个数就有
(
M
d
)
N
(\frac{M}{d})^N
(dM)N 种情况,但是 这里面还有重复的,就需要容斥了,容斥系数就是莫比乌斯函数,做了上一道题,这次反应过来了嘻嘻
但是一想,1~M每个数都要容斥么?这样不是就T了么?
但是阔以发现,如果这N个数d不是M的因子,那么与M再求个gcd,那就肯定是1了得哇,因此,只用容斥他的因子就行了
#include"iostream"
#include"cstring"
#include"vector"
#include"map"
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int MOD=1e9+7;
int mu[maxn];
bool vis[maxn];
vector<LL>prime;
LL ksm(LL a,LL b)
{
LL res=1,base=a;
while(b)
{
if(b&1)res=(res*base);
base=(base*base);
b>>=1;
}
return res;
}
void PHI(int n)
{
memset(vis,1,sizeof(vis));
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(vis[i])
{
prime.push_back(i);
mu[i]=-1;
}
for(int j=0;j<prime.size()&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=0;
if(i%prime[j]==0)break;
else
{
mu[i*prime[j]]=-mu[i];
}
}
}
}
LL Mu(LL n)
{
if(n<=maxn-5)return mu[n];
int cnt=0,u=1;
for(LL i=0;prime[i]*prime[i]<=n;i++)
{
cnt=0;
if(n%prime[i]==0)u=-u;
while(n%prime[i]==0)
{
n/=prime[i];
cnt++;
}
if(cnt>=2)return 0;
}
if(n>1)u=-u;
return u;
}
vector<LL>factor;
int main()
{
PHI(maxn-5);
LL N,M;
while(cin>>N>>M)
{
factor.clear();
for(LL i=1;i*i<=M;i++)
{
if(M%i==0)
{
factor.push_back(i);
if(i==M/i)continue;
factor.push_back(M/i);
}
}
LL ans=0;
for(int i=0;i<factor.size();i++)//只有M的因子才容斥,不然肯定与M是互质的
{
LL d=factor[i];
LL cnt=M/d;
LL tp=ksm(cnt,N)*Mu(d);
ans+=tp;
}
cout<<ans<<endl;
}
}