题意:
有。给定m,n,p,求。其中,,p为质数。
思路:
可以推导出。
举个例子形象一点,
因为有欧拉公式,其中x,y为n的质因子。
化简后分母只剩下的质因子的部分,上下同乘,得
这里分子就是,分母则是中减去2的倍数的个数,减去3的倍数的个数,加上6的倍数的个数,这个容斥就是求出了比小的数中与它互质的数的个数,即。
所以问题就转化为了求。这里用到了容斥。
枚举。设f[i]:gcd为i的倍数的(a,b)对数,g[i]:gcd为i的(a,b)对数。
以a=6,b=8为例,
。
所以就可以求出g[i]了。
代码:
#define MAXN 1000000
typedef long long ll;
ll eu[MAXN+10];
ll pri[MAXN+10];
bool vis[MAXN+10];
ll f[MAXN+10];//gcd为i的倍数的对数
ll g[MAXN+10];//gcd为i的对数
ll inv[MAXN+10];
void init()
{
eu[1]=1;
ll cnt=0;
for(ll i=2;i<=MAXN;i++)
{
if(!vis[i]){pri[cnt++]=i;eu[i]=i-1;}
for(int j=0;j<=cnt&&pri[j]*i<=MAXN;j++)
{
vis[i*pri[j]]=1;
if(i%pri[j]==0)
{
eu[i*pri[j]]=eu[i]*pri[j];
break;
}
eu[i*pri[j]]=eu[i]*(pri[j]-1);
}
}
}
long long PowerMod(ll a,ll b,ll c)
{
long long ans=1;
long long k;
k=a;
while(b>0)
{
if(b%2==1)
ans=(ans*k)%c;
b=b/2;
k=(k*k)%c;
}
return ans;
}
int main()
{
int t;
ll m,n,p;
init();
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld",&m,&n,&p);
ll ans=0;
for(ll i=1;i<=min(m,n);i++)
f[i]=(m/i)*(n/i);
ll tot=min(m,n);
inv[1]=1;
for(ll i=2;i<=tot;i++)
inv[i]=(p-(p/i))*inv[p%i]%p;
for(ll i=tot;i>=1;i--)
{
g[i]=f[i];
for(ll j=2;i*j<=tot;j++)
g[i]=(g[i]-g[i*j]+p)%p;
ll temp=g[i];
temp=((temp*i)%p*inv[eu[i]])%p;
ans=(ans+temp)%p;
}
printf("%lld\n",ans);
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!