G - GuGuFishtion HDU - 6390

G - GuGuFishtion

HDU - 6390

Today XianYu is too busy with his homework, but the boring GuGu is still disturbing him!!!!!!
At the break time, an evil idea arises in XianYu's mind.
‘Come on, you xxxxxxx little guy.’
‘I will give you a function ϕ(x) which counts the positive integers up to x that are relatively prime to x.’
‘And now I give you a fishtion, which named GuGu Fishtion, in memory of a great guy named XianYu and a disturbing and pitiful guy GuGu who will be cooked without solving my problem in 5 hours.’
‘The given fishtion is defined as follow:

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


And now you, the xxxxxxx little guy, have to solve the problem below given m,n,p.’

(∑a=1m∑b=1nGu(a,b))(modp)


So SMART and KINDHEARTED you are, so could you please help GuGu to solve this problem?
‘GU GU!’ GuGu thanks.

Input

Input contains an integer T

indicating the number of cases, followed by T lines. Each line contains three integers m,n,p as described above.
1≤T≤3
1≤m,n≤1,000,000
max(m,n)<p≤1,000,000,007
And given p

is a prime.

Output

Please output exactly T

lines and each line contains only one integer representing the answer.

Sample Input

1
5 7 23

Sample Output

2

参考博客:

欧拉函数的理解和求解:

https://blog.csdn.net/Willen_/article/details/85716688

莫比乌斯反演:

https://blog.csdn.net/Willen_/article/details/85565654

逆元的求解:

https://blog.csdn.net/Willen_/article/details/85367841

其中:以上公式g(m,n)要求的是[1,m]和[1,n]满足gcd为1的数对的个数,设F(i)为满足gcd%i==0的数对个数,f(i)为满足gcd==i的数对个数,那么显然F(i)=(m/i)*(n/i),需要求的是f(1),根据莫比乌斯反演公式

 

#include<iostream>
#include<cstring>
typedef long long ll;
using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 1000010;

ll phi[MAXN];
ll mu[MAXN];
ll inv[MAXN];
ll a[MAXN];

//void euler(ll n){
//    for(int i=1;i<=n;i++) phi[i]=i;
//    for(int i=2;i<=n;i++){

//        if(phi[i]==i){
//            for(int j=i;j<=n;j+=i){
//                phi[j] = phi[j]/i*(i-1);
//            }
//        }
//    }
//}


void euler(){

    memset(phi,0,sizeof(phi));

    phi[1]=1;

    for(int i=2;i<MAXN;i++){
        if(!phi[i]){
            for(int j=i;j<MAXN;j+=i ){

                if(!phi[j])
                    phi[j]=j;
                phi[j]=phi[j]/i*(i-1);
            }
        }
    }
}


void getMu(){

    mu[1]=1;
    for(int i=1;i<MAXN;i++)
        for(int j=2*i;j<MAXN;j+=i){
            mu[j]-=mu[i];
        }
}


void getInv(int n,int m,ll p){

    inv[1]=1;
    for(int i=2;i<=min(n,m);i++) inv[i] = inv[p%i]*(p-p/i)%p;
}

ll get(int n,int m,ll p){
    ll ans =0;
    for(int i=1;i<=min(n,m);i++){
        ans+=(ll)mu[i]*(n/i)*(m/i);
        ans%=p;
    }
    return ans;
}

void init(int n,int m,ll p){

    for(int i=1;i<=min(n,m);i++){
        a[i]=(ll)i*inv[phi[i]]%p;
    }

}


int main(){

    int T;
    scanf("%d",&T);

    euler();
    getMu();
    while(T--){
        int m,n;
        ll p;
        scanf("%d %d %lld",&m,&n,&p);

        getInv(n,m,p);
        init(n,m,p);

        ll ans=0;
        for(int i=1;i<=min(m,n);i++){
            ans+=(ll)a[i]*get(n/i,m/i,p);
            ans%=p;
        }

        printf("%lld\n",ans);
    }
    return 0;
}

 需要注意的点。之前因为设置函数传入为m,n 为long long 型而导致超时,改为int 类型 则通过

猜你喜欢

转载自blog.csdn.net/Willen_/article/details/85721497