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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值