题目
题目描述
给出 \(N\) ,求 \(1\) 到 \(N\) 个数中选出任意个数相乘能组成的最大平方数,由
于此数可能很大,你只需要输出此数除 \(100000007\) 的余数即可。
样例输入
1 2 |
7 |
样例输出
1 2 |
144 |
样例解释
\(2\times 3 \times 4\times 6=144\)数据下载
由于各大oj可能没有,故在此提供测试数据
题解
题目就是这么简单,然而考试并没有想到\(QAQ\)
因为是任意个数相乘,我们可以将\(N!\)进行质因数分解
然后因为\(A^2\times B^2=(A\times B)^2\)
我们就可以把所有的2的整数倍次方全部乘入答案里,就是最大的平方数。
而普通的方法分解\(N!\)需要\(O(N\sqrt{N})\)的时间复杂度,我们可以考虑一种新方法。
显然,\(N!\)的每个质因子都不会超过\(N\),我们可以先筛选出\(1-N\)的每个质数\(p\),然后考虑阶乘中一共包含多少个质因子\(p\)
\(N!\)中质因子\(p\)的个数就等于\(1-N\)每个数包含的质因子\(p\)的个数之和。在\(1-N\)中,\(p\)的倍数,即至少包含1个质因子\(p\)的显然有\(\lfloor N/p \rfloor\)个。而\(p^2\)的倍数,即至少包含2个质因子\(p\)的有\(\lfloor N/p^2 \rfloor\)个。不过其中的一个质因子已经在\(\lfloor N/p \rfloor\)中统计过,所以只需要再统计第2个质因子,即累加上\(\lfloor N/p^2 \rfloor\),而不是\(2\times \lfloor N/p^2 \rfloor\)
综上所述,\(N!\)中质因子\(p\)的个数为:
\left\lfloor \frac{N}{P} \right\rfloor+\left\lfloor \frac{N}{P^2} \right\rfloor+\left\lfloor \frac{N}{P^3} \right\rfloor+\dots+\left\lfloor \frac{N}{P^{\lfloor log_p N \rfloor}} \right\rfloor=\sum_{p^k\le N}\left\lfloor \frac{N}{P^k} \right\rfloor
上面的计算只需要\(O(logN)\)的时间
整个过程只需要\(O(NlogN)\)的时间
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#include<iostream> #include<cstdio> #include<vector> using namespace std; const int mod=100000007; int n,ans=1; bool v[10000010]; vector<int> prime; void get_prime(int n){ for(int i=2;i<=n;i++){ if(v[i])continue; prime.push_back(i); for(int j=i;j<=n/i;j++)v[i*j]=1; } } int main(){ cin>>n; get_prime(n); for(int i=0;i<prime.size();i++){ int p=prime[i],c=0; for(int j=n;j;j/=p)c+=j/p; if(c==0)continue; if(c&1){ for(int i=1;i<c;i++)ans=(long long)ans*p%mod;//这里要么取两次mod,要么用long long,后者快一点,当然可以用快速幂,更快(我懒orz } else for(int i=1;i<=c;i++)ans=(long long)ans*p%mod;//这里要么取两次mod,要么用long long,后者快一点,当然可以用快速幂,更快 } cout<<ans; return 0; } |