题意:给定一个n,而后让你从1-n中选出某些数乘起来,使得乘积最大,而且乘积必须是彻底平方数。ide
思路:将1-n种每一个数都分解素因子,把他们的素因子的幂加起来,若是是偶数,就说明能够构成彻底平方数,乘起来,若是是奇数,说明不能构成,减去一个就是偶数了,因此减去一个再乘起来。由于要分解1-n当中全部的素因子,而后乘起来,那么也就是分解n!的素因子,因此只要找出来他的全部的素因子的幂指数为奇数的直接除就好了。如今有个问题是不能除。要取模,更好的方法是,再算n!的时候,不乘素数,那样的话,就到最后再乘。若是是奇次幂,就不用乘,偶次幂再乘。这样的话,就须要找出1-n当中素因子是多少次幂,方法是,直接用n除以素因子,而后加起来,知道n为0。具体见代码。spa
吐嘈:这个题意彻底读不懂啊。。。看了题解才知道的。还有就是这种方法太奇妙了。赞赞赞!code
#include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 10000010; const ll mod = 1000000007LL; const int sqrtmaxn = (int)(sqrt((double)maxn)); ll fac[maxn]; int prime[maxn]; int cnt; void init() { memset(prime, 0, sizeof(prime)); fac[0] = fac[1] = 1;//阶乘 cnt = 0; for (int i = 2; i < maxn; i++) { fac[i] = fac[i - 1]; if (prime[i] == 0)//若是是素数,就先不乘 { prime[cnt++] = i; if (i <= sqrtmaxn) for (int j = i * i; j < maxn; j += i) prime[j] = 1; } else fac[i] = (fac[i] * i) % mod;//不是素数直接乘 } } int main() { init(); int n; while (~scanf("%d", &n) && n) { ll ans = fac[n]; for (int i = 0; i < cnt && prime[i] <= n; i++) { int tot = 0, tmp = n;//tmp统计素因子的幂次 while (tmp) tot += (tmp /= prime[i]); if ((tot & 1) == 0) ans = (ans * prime[i]) % mod; } printf("%d\n", (int)ans); } return 0; }