poj1091 跳蚤

文章目录

题目链接:

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;
		
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值