hdu 1454 Happy 2004(数论,分解因子,乘法逆元,快速幂取模)

Happy 2004

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1413    Accepted Submission(s): 1029


Problem Description
Consider a positive integer X,and let S be the sum of all positive integer divisors of 2004^X. Your job is to determine S modulo 29 (the rest of the division of S by 29).

Take X = 1 for an example. The positive integer divisors of 2004^1 are 1, 2, 3, 4, 6, 12, 167, 334, 501, 668, 1002 and 2004. Therefore S = 4704 and S modulo 29 is equal to 6.
 

Input
The input consists of several test cases. Each test case contains a line with the integer X (1 <= X <= 10000000). 

A test case of X = 0 indicates the end of input, and should not be processed.
 

Output
For each test case, in a separate line, please output the result of S modulo 29.
 

Sample Input
  
  
1 10000 0
 

Sample Output
  
  
6 10
题意:给你一个x,问你2004的x次方的因子和对29取余结果是多少

思路:将2004分解质因子,并分别将指数乘以x即可得到公式,我们知道x=p1的e1次方*p2的e2次方*p3的e3次方...*pk的ek次方(p均为质数,e均为整数)

那么因子和为(1+p1+p1的2次方+...p1的e1次方)*...*(1+pk+pk的2次方+...pk的ek次方)

而1+p1+p1的2次方+...p1的e1次方=(p1的(e1+1)次方-1)/(p1-1) 因为此处需要取模,所以需要对p1-1用乘法逆元

代码一:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define mod 29
int e[10][2];
int cnt;
void devide(int n)
{
    cnt=0;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            int num=0;
            while(n%i==0)
            {
                num++;
                n/=i;
            }
            e[++cnt][0]=i,e[cnt][1]=num;
        }
    }
    if(n>1) e[++cnt][0]=n,e[cnt][1]=1;
}
int pow_mod(int a,int n)
{
    int ans=1;
    while(n)
    {
        if(n&1) ans=ans*a%mod;
        a=a*a%mod;
        n/=2;
    }
    return ans;
}
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
int extend_gcd(int a,int b,int &x,int &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    int x1=x,y1=y;
    int d=extend_gcd(b,a%b,x1,y1);
    x=y1;
    y=x1+(a/b)*y1;
    return d;
}
int mod_reverse(int a,int n)
{
    int x,y;
    int d=extend_gcd(a,n,x,y);
    if(d!=1) return -1;
    return (x%n+n)%n;
}
int main()
{
    int x;
    devide(2004);
    while(~scanf("%d",&x)&&x)
    {
        int ans=1;
        for(int i=1;i<=cnt;i++)
        {
            int inv=mod_reverse(e[i][0]-1,mod);
            ans=(ans*(pow_mod(e[i][0],e[i][1]*x+1)-1)%mod*inv)%mod;
        }
        printf("%d\n",ans);
    }
    return 0;
}
或者可以用公式x/d%k==x%(d*k)/d这样就可以直接得到答案了。注意取模就要全部都对(d*k)取了~

代码二

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define LL long long
#define N 10000010
LL pow_mod(LL a,LL n,int mod)
{
    LL ans =1;
    while(n)
    {
        if(n&1) ans=ans*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans;
}
int main()
{
    LL T,x;
    while(scanf("%lld",&x)&&x)
    {
        LL temp2=pow_mod(2,2*x+1,29*332)-1;
        LL temp3=pow_mod(3,x+1,29*332)-1;
        LL temp167=pow_mod(167,x+1,29*332)-1;
        LL ans=temp2*temp3*temp167%(29*332)/332;
        printf("%lld\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值