HDU 4196 Remoteland

題意:給定一個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;
}
View Code
相關文章
相關標籤/搜索