hdu 6390 GuGuFishtion 欧拉函数性质+容斥

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6390

 

Gu(a,b)=ϕ(ab)/ϕ(a)ϕ(b)

现在求a从1到n,b从1到m的Gu(a,b)的总和

由欧拉函数的表达式,n可分解为p1^a1*p2^a2*...pn^an

则φ(n)=∏(pi-1)(pi^(ai-1))

将a和b分解质因数,设a和b都有质因数p,a中一项为p^a1,b中一项为p^a2,则

当a1=0时,原式中此项为1,。所以只有ab同时含有p这个质因数时,才会对答案有所贡献。

在最后的式子中,对于每个分子中的p和分母中的(p-1)都将他们加上对应a1、a2的最小值的次幂,原式就变成了:
(a,b)/φ((a,b))

之后就是容斥

f【i】代表gcd为i的倍数的ab对数

g【i】代表gcd为i的ab对数

从后向前O(n)遍历f【i】=(n/i)*(m/i);

g【i】=f【i】-f【i*2】-f【i*3】。。。。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;

const LL N=1000000;
int pr[N/5],p[N+100],tot,phi[N+100];
LL f[N+10],inv[N+10];
int n,m,mod;
void init()
{
    phi[1]=1;p[1]=1;
    For(i,2,N){
        if(!p[i])p[i]=i,pr[++tot]=i,phi[i]=p[i]-1;
        for(int j=1;j<=tot&&pr[j]*i<=N;j++){
            p[i*pr[j]]=pr[j];
            if(p[i]==pr[j]){
                phi[i*pr[j]]=phi[i]*pr[j];
                break;
            }else phi[i*pr[j]]=phi[i]*(pr[j]-1);
        }
    }
}

int main()
{
    init();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&mod);
        n=min(n,m);
        inv[1]=1;
        for(int i=2;i<=n;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
        LL ans=0;
        for(int i=n;i>=1;i--)
        {
            f[i]=(LL)(n/i)*(m/i);
            for(int j=i+i;j<=n;j+=i)f[i]=f[i]-f[j];
            ans=(ans+f[i]%mod*i%mod*inv[phi[i]])%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值