尤拉計劃386題(反鏈的最大長度) 論壇c++解法學習筆記

lt發表於2016-12-11

這是stubbscroll的帖子,他也沒有把程式碼貼全。我補充了生成最小質因數部分。有趣的是,如果生成的不是最小質因數,也能出正確答案,速度也差不多。要使生成的不是最小質因數,把for(int j=i*i; j<=N; j+=i*((i>2)?2:1))的步長改為j+=i。這樣會把12的最小質因數2用3覆蓋。divs原來是向量,我改為陣列後,放在main函式內,會執行出錯,因此移動到外面。

#include<vector>
#include<cstdio>
#include<cmath>
#include<ctime>
using namespace std;
#define N 100000000
#define P(X) printf("%s %ldms\n",X,clock()-t);fflush(stdout);

int divs[N+1]= {0};
int main()
{

    int t=clock();
    //vector<int> divs = genPrimes(N, true); // minimal divisors

    divs[1]=1;
    for(int i=2; i<=sqrt(N); i++)//i+=(i>2)?2:1) slower
        if(divs[i]==0)
        {
            for(int j=i*i; j<=N; j+=i*((i>2)?2:1))
                divs[j]=i;
            divs[i]=i;
        }
    for (int i = 2; i <= N; ++i)
        if(divs[i]==0)divs[i]=i;//prime's fact is itself
    P("gen prime min factor done");
    vector<int> degs(N + 1);
    vector< vector<int> > byDegs(30);
    degs[1] = 0;
    byDegs[0].push_back(1);
    for (int i = 2; i <= N; ++i)
    {
        degs[i] = degs[i / divs[i]] + 1;
        byDegs[degs[i]].push_back(i);
    }
    P("gen degress done");

    long long ans = 0;
    for (int i = 0; i < 29; ++i)
    {
        int low = 0, high = byDegs[i].size() - 1;
        while (low < byDegs[i].size())
        {
            while (high >= 0 && (long long)byDegs[i][high] * byDegs[i][low] > N)
            {
                --high;
            }
            ans += high + 1;
            ++low;
        }
        low = 0, high = byDegs[i + 1].size() - 1;
        while (low < byDegs[i].size())
        {
            while (high >= 0 && (long long)byDegs[i + 1][high] * byDegs[i][low] > N)
            {
                --high;
            }
            ans += high + 1;
            ++low;
        }
    }

    printf("%lld\n", ans);
    P("all done")
}
--正確最小質因數
D:\>a
gen prime min factor done 1903ms
gen degress done 4056ms
528755790
all done 5319ms
--不正確最小質因數
D:\>a
A 2730ms
gen prime min factor done 2979ms
gen degress done 5257ms
528755790
all done 6552ms

上述j+=i*((i>2)?2:1)只能保證偶數不被覆蓋,參考了stubbscroll發的前一貼,還要加上if(divs[j]==0)才能保證所有最小質因數都不被覆蓋。但反正算錯也能出正確答案,這個條件不加也行。

相關文章