hdu 4196 Remoteland(数论,2种求逆模的方法)

Remoteland

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)
Total Submission(s): 908    Accepted Submission(s): 332


Problem Description
In the Republic of Remoteland, the people celebrate their independence day every year. However, as it was a long long time ago, nobody can remember when it was exactly. The only thing people can remember is that today, the number of days elapsed since their independence (D) is a perfect square, and moreover it is the largest possible such number one can form as a product of distinct numbers less than or equal to n.
As the years in Remoteland have 1,000,000,007 days, their citizens just need D modulo 1,000,000,007. Note that they are interested in the largest D, not in the largest D modulo 1,000,000,007.
 

Input
Every test case is described by a single line with an integer n, (1<=n<=10,000, 000). The input ends with a line containing 0.
 

Output
For each test case, output the number of days ago the Republic became independent, modulo 1,000,000,007, one per line.
 

Sample Input
  
  
4 9348095 6297540 0
 

Sample Output
  
  
4 177582252 644064736
 

Source
 

题意:用不大于n内的所有数组成一个最大的完全平方数

题解:就是把N!这个数的个数为奇数的素因子除掉,于是就是一个求逆模的问题了,逆模可以用快速幂求,也可以用扩展欧几里得

这里有更加详细的题解 http://blog.csdn.net/acm_cxlove/article/details/7422265



#include<stdio.h>
#include<string.h>
#include<math.h>
#define mod 1000000007
int prime[1000008],flag[10000008],all=0;
long long res[10000008],sum;
void init()
{
    long long i,j,cc=sqrt(10000001.0);
    memset(flag,0,sizeof(flag));
    res[0]=res[1]=1;
    for(i=2;i<=cc;i++)
    {
        if(flag[i]) continue;
        for(j=i*i;j<=10000000;j+=i) flag[j]=1;
    }
    for(i=2;i<=10000000;i++)
    {
        res[i]=(res[i-1]*i)%mod;
        if(!flag[i]) prime[all++]=i;
    }
}
int get_sum(int x,int n)
{
    int ans=0;
    while(n)
    {
        ans+=n/x;
        n=n/x;
    }
    return ans;
}
int fpow(long long x,long long n)
{
    long long ans=1;
    while(n)
    {
        if(n&1) ans=(ans*x)%mod;
        n>>=1;
        x=(x*x)%mod;
    }
    return ans;
}
void exgcd(int a,int b,int *gcd,int *x,int *y)
{
    if(!b){ *gcd=a; *x=1; *y=0; }
    else{ exgcd(b,a%b,gcd,y,x); *y-=*x*(a/b); }
}
int get_inverse_model(int tag,int MOD)
{
    //return fpow(tag,MOD-2);

    int gcd,x,y;
    exgcd(tag,MOD,&gcd,&x,&y);
    return (x+MOD)%MOD;
}
int main()
{
    int i,n,cou;

    init();
    while(scanf("%d",&n),n)
    {
        for(sum=1,i=0;i<all&&prime[i]<=n;i++)
        {
            cou=get_sum(prime[i],n);
            if(cou&1) sum=(sum*prime[i])%mod;
        }
        //printf("cc   %I64d\n",sum);
        printf("%d\n",(int)((res[n]*get_inverse_model(sum,mod))%mod));
    }

    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值