hdoj 4196 Remoteland 【阶乘因式分解中质因子个数 + 费马小定理】



Remoteland

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


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
 


题意:给一个数n,要求从[1, n]中选出若干个数,使它们乘积为完全平方数A。现在问你最大的A % 100000007是多少。


由算术基本定理——

任何一个大于1的自然数

   
,都可以唯一分解成有限个质数的乘积
   
,这里
   
均为 质数 ,其诸指数
   
是正整数。

这样我们就可以得出结论:最大的完全平方数A = n! / (res),其中res=[1, n]中所有指数为奇数的质数乘积。

求解阶乘中质数p的 指数:

int sum = 0;
while(n)
{
    sum += n / p;
    n /= p;
}
sum...


由费马小定理——

a ^ (m-1) = 1 (%m) ——> a ^ (m-2) = a ^ -1 (%m),其中a为整数,m为质数且a不是m的倍数。

上述结果转化A = n! * res ^ (MOD-2) % MOD。



AC代码:


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define MAXN 10000000+1
#define MOD 1000000007
#define LL long long
using namespace std;
int Prime[MAXN];
int vis[MAXN];
int top;
void getp()
{
    memset(vis, 0, sizeof(vis));
    for(int i = 2; i < MAXN; i++)
    {
        if(!vis[i])
        {
            for(int j = 2*i; j < MAXN; j+=i)
                vis[j] = 1;
        }
    }
    top = 0;
    for(int i = 2; i < MAXN; i++)
        if(!vis[i])
            Prime[top++] = i;
}
LL f[MAXN];//存储阶乘
void getf()
{
    f[1] = 1;
    for(int i = 2; i < MAXN; i++)
        f[i] = f[i-1] * i % MOD;
}
int num(int n, int p)
{
    int sum = 0;
    while(n)
    {
        sum += n / p;
        n /= p;
    }
    return sum;
}
LL pow_mod(LL a, LL n)
{
    LL ans = 1;
    while(n)
    {
        if(n & 1)
            ans = ans * a % MOD;
        a = a * a % MOD;
        n >>= 1;
    }
    return ans;
}
int main()
{
    getp();
    getf();
    int n;
    while(scanf("%d", &n), n)
    {
        LL res = 1;
        for(int i = 0; i < top && Prime[i] <= n; i++)//注意结束条件 还有i < top
        {
            if(num(n, Prime[i]) & 1)
                res = res * Prime[i] % MOD;
        }
        printf("%lld\n", f[n] * pow_mod(res, MOD-2) % MOD);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值