完全平方数(数论)

完全平方数

题目概述:

从1−N中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数最大可能是多少(答案取模100000007)
(数据说明:对于20%的数据,1≤N≤100.对于50%的数据.1≤N≤5000.对于70%的数据,1≤N≤10^5.对于100%的数据,1≤N≤5×10^6.)

题目分析:

首先考虑什么是合法解——完全平方数,那么对其进行质因数分解之后得到的每种质因数的个数应当是偶数个.那么,只要保证选取的数质因数分解后每种个数为偶数个,就能满足完全平方数要求.那么问题就转换到求解1~N的任意质因数个数(对于个数为偶数的质数直接取完,个数为奇数的质数去掉该质数本身即可),如何快速求1~N的某一质因数个数.首先可以考虑这样一个问题:如何统计1~N的所有因数个数,实际上可以发现1的因数个数=N/1,2的因数个数=N/2…那么则有如下式子:

那么这个问题就便于解决了,举个例子,如求1~81的3的个数是多少,可以发现ans=81/3+27/3+9/3+3/3=40,那么就可以得到如下式子(好吧,我不会推导式子(逃)):

代码:

#include
#include
#include

using namespace std;

typedef long long ll;
const int MOD=100000007;
const int maxp=500000+10;
const int maxn=5000000+10;

int pri[maxn],notpri[maxn],pcnt;

void init(int n)//筛素数
{
    for(int i=2;i<=n;i++) if(!notpri[i]) {
        pri[++pcnt]=i;
        for(ll j=(ll)i*i;j<=n;j+=i) notpri[j]=1;
    }
}

int count(int p,int n)//计算每个素数出现次数
{
    int ret=0;
    while(n>=1) {
        ret+=n/p;
        n/=p;
    }
    return ret;
}

int pow_mod(int x,int y)//快速幂
{
    int ans=1;
    while(y>0) {
        if(y&1) ans=((ll)ans*x)%MOD;
        x=(ll)x*x%MOD;y>>=1;
    }
    return ans;
}

int main()
{
    int N,ans=1;
    scanf("%d",&N);
    init(N);
    for(int i=1;i<=pcnt;i++) {
        int k=count(pri[i],N);
        if(k%2) --k;
        ans=((ll)ans*pow_mod(pri[i],k))%MOD;
    }
    printf("%d",ans);
    return 0;
}

你可能感兴趣的:(数学-数论)