UOJ 188 [UR #13]Sanrd(min_25篩)

Description

這裏是跳蚤國中央廣播電臺,現在爲您轉播的是著名人類智慧大師picks 博士與人工智能betacome 之間的最後一輪賽事。

這一場交鋒的規則由網友stll 提供,這位網友也將獲得由不想跳的跳蚤不是好跳蚤——最強跳蚤跳跳跳公司提供的金牌跳蚤一隻。

就在剛纔,第二輪比賽也已經結束了,picks 博士不負衆望爲人類扳回了一城。特別是在剛纔劣勢的時候,picks 博士突然地停止了對盤子的操作,讓betacome 亂了陣腳,並最後實現了反超,這一手操作也被網友戲稱爲“神之一手”。

“恩,這一手錶明瞭betacome 也是存在弱點而不是不可戰勝的,picks 博士可能也在一直嘗試着不同的比賽風格,試圖找到betacome 的漏洞。上一場的勝利說明了betacome 在對於突發事件的應對方式可能存在着缺陷,在這一輪picks 博士應該會針對這一點進行比賽,我認爲他的勝率應該會非常大。”

那看來A 先生抱着非常樂觀的心態啊,現在最後一輪的比賽已經開始了,同樣,接下來由A 先生來給我們介紹一下這一輪比賽的規則。

“好,大家現在看屏幕,在這一輪遊戲中,給出了一個如下所示的將n 分解質因子的算法。”

  1. 檢查n 是否是質數,假如n 是質數或n=1 則直接結束。
  2. 定義一個變量p ,初始值爲2
  3. 檢查p 是否是n 的因子,假如pn 的因子,不斷將n 除去p ,直到p 不再是n 的質因子。
  4. 檢查n 是否是質數,假如n 是質數或n=1 ,就結束這個算法,否則將p 的值加一,返回第三步。

“爲了檢驗人類智慧和人工智能之間的計算能力的差距,主辦方希望選手對區間[l,r] 中的所有數都用這個算法進行分解。爲了檢驗計算的正確性,選手需要計算分解完每一個數後,p 的和。特殊地,如果分解在第一步就結束了,那麼就認爲p=0

恩,謝謝A 先生。大家可以看到這一道是數論方面的題目,剛纔A 先生也私下和我說了,這一道題目的難度要比前兩輪的難度高很多,他認爲在短時間內,比賽雙方都無法得到準確的結果。因爲我們節目組決定與觀衆們進行互動,正在收看節目的觀衆可以關注節目跳蚤信公衆號參與解題,最快得到正確答案的觀衆將會獲得由不想跳的跳蚤不是好跳蚤——最強跳蚤跳跳跳公司提供的精美禮品一份。

作爲一名光榮的吃土少年,你立志要把這份禮品收入囊中以告別悲慘的吃土生活。然而,全世界的觀衆中也不乏人類智慧大師的存在,爲了從他們中脫穎而出,你需要以最快的速度得到這一個問題的答案。

Input

一行兩個正整數l,r ,表示需要分解的數的範圍(1lr1011)

Output

輸出一行一個整數,表示每次分解結束時,變量p 的值之和。

Sample Input

16 20

Sample Output

7

Solution

f(n) 爲分解n 結束時的p 值,若n1 或素數則有f(p)=0 ,否則f(n) 即爲n 的次大素因子

假設ni 的取值分別爲val1,...,valcntn 以內的素數爲p1,...,pm ,設S(i,j)[1,vali] 中最小素因子不小於pj 的數字的f 值之和,顯然其中的素數沒有貢獻,對於其中的合數,枚舉起最小素因子pk 以及其冪指數e ,那麼數字有兩種:pkepl(lk)pken ,其中n 爲最小素因子大於pk 的合數,第一種對答案的貢獻爲pk ,第二種對答案的貢獻爲n 對答案的貢獻,進而有轉移

S(i,j)=kjpke+1vali(S(valipke,k+1)+pkp=pkvali[p])

min_25 篩求出g(i) 表示[1,vali] 中素數個數,那麼最後一個求和即爲g(i)(k1)

Code

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 700005
int p[maxn],f[maxn],np=0,m=350000;
void get_prime(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!f[i])p[++np]=i;
        for(int j=1;j<=np&&i*p[j]<=n;j++)
        {
            f[i*p[j]]=1;
            if(i%p[j]==0)break;
        }
    }
    np--;
}
ll val[maxn],n;
int nn,cnt;
void init()
{
    nn=1;
    while((ll)nn*nn<n)nn++;
    cnt=0;
    for(ll i=1;i<=n;i=n/(n/i)+1)val[++cnt]=n/i;
}
int ID(ll x)
{
    if(x>=nn)return n/x;
    return cnt-x+1;
}
ll g0[maxn];
void Get_g(ll n)
{
    for(int i=1;i<=cnt;i++)g0[i]=val[i]-1;
    for(int j=1;j<=np;j++)
        for(int i=1;i<=cnt&&(ll)p[j]*p[j]<=val[i];i++)
        {
            int k=ID(val[i]/p[j]);
            g0[i]=g0[i]-(g0[k]-(j-1));
        }   
    return ;
}
ll S(ll i,int j)
{
    if(i<=1||p[j]>i)return 0;
    int k=ID(i);
    ll ans=0;
    for(int k=j;k<=np&&(ll)p[k]*p[k]<=i;k++)
    {
        ll p1=p[k],p2=(ll)p[k]*p[k];
        for(int e=1;p2<=i;p1=p2,p2*=p[k],e++)
            ans+=S(i/p1,k+1)+(g0[ID(i/p1)]-k+1)*p[k]; 
    }
    return ans;
}
int main()
{
    get_prime(m);
    scanf("%lld",&n);
    n--;
    init();
    Get_g(n);
    ll ans=-S(n,1);
    scanf("%lld",&n);
    init();
    Get_g(n);
    ans+=S(n,1);
    printf("%lld\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章