2017 Multi-University Training Contest - 第二場 07 If the starlight never fade (數論)

題目鏈接:
HDU 6051

題意:
f(i)  表示滿足(x+y) i x i %p (x,y)  的對數,其中,1xp1,1ym. 
給你一個非負數 m  和素數 p  ,讓你求 p1 i=1 if(i)  ,答案mod1e9+7 

題解:
數學題。

g p  的原根,x=g a ,y=g b  
那麼有(g a +g b ) i =g ai %p  。即(1+g ba ) i =1%p 
1+g ba =g k   ,則有g ki =1%p  ,即ki%(p1)=0 

因爲 0<k<p1  ,所以 k  的取值有gcd(i,p1)1  個,遞推回去,可知x=yinv(g k 1)  ,故x  的取值也是gcd(i,p1)1  個。

所以我們最後只需要求m p1 i=1 {igcd(i,p1)i} 
其中 p1 i=1 i  ,我們可以直接求出。

而另一部分 p1 i=1 igcd(i,p1)  ,我們可以通過枚舉gcd  的值,化爲 d|(p1) d 2  p1d  k=1 k[gcd(k,p1d )=1] 
然後根據公式 n i=1 i[gcd(i,n)=1]=(nφ(n)+[n=1])/2  求解。
其中,φ(n)  爲歐拉函數。

AC代碼:

#include<bits/stdc++.h>
const int mod = 1e9+7;
using namespace std;
typedef long long ll;

int mod_mul(int a,int b)
{
    ll c = 1LL * a * b;
    return c - c / mod * mod;
}

int euler(int n) 
{
    int ret = n;
    int i;
    for(i = 2 ; i * i <= n ; i ++)
    {
        if(n % i == 0)
        {
            ret = ret - ret / i;
            while(n % i == 0)
            {
                n /= i;
            }
        }
    }
    if(n > 1)
    {
        ret = ret - ret / n;
    }
    return ret;
}

int solve(int n)
{
    int ans = 0;
    int tmp = 0;
    for(int i = 1 , j ; i * i <= n; i++)
    {
        j = n / i;
        if(i * j == n)
        {
            tmp = mod_mul( (1LL * j * euler(j) + ( j == 1 ) ) / 2 % mod, mod_mul( i , i ) );
            if((ans += tmp) >= mod) ans -= mod;


            if(i != j)
            {
                tmp = mod_mul( (1LL * i * euler(i) + ( i == 1 ) ) / 2 % mod, mod_mul( j , j ) );
                if((ans += tmp) >= mod) ans -= mod;
            }

        }
    }
    ans -= mod_mul( mod_mul( n, n + 1), 500000004);
    if(ans < 0) ans += mod;
    return ans;
}
int main()
{
    int t;
    int m,p,cas=0;
    scanf("%d",&t);
    while(t--)
    {
        cas++;
        scanf("%d%d",&m,&p);
        int ans = mod_mul( solve(p - 1), m );
        printf("Case #%d: ",cas);
        printf("%d\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章