Description
這裏是跳蚤國中央廣播電臺,現在爲您轉播的是著名人類智慧大師 博士與人工智能 之間的最後一輪賽事。
這一場交鋒的規則由網友 提供,這位網友也將獲得由不想跳的跳蚤不是好跳蚤——最強跳蚤跳跳跳公司提供的金牌跳蚤一隻。
就在剛纔,第二輪比賽也已經結束了, 博士不負衆望爲人類扳回了一城。特別是在剛纔劣勢的時候, 博士突然地停止了對盤子的操作,讓 亂了陣腳,並最後實現了反超,這一手操作也被網友戲稱爲“神之一手”。
“恩,這一手錶明瞭 也是存在弱點而不是不可戰勝的, 博士可能也在一直嘗試着不同的比賽風格,試圖找到 的漏洞。上一場的勝利說明了 在對於突發事件的應對方式可能存在着缺陷,在這一輪 博士應該會針對這一點進行比賽,我認爲他的勝率應該會非常大。”
那看來 先生抱着非常樂觀的心態啊,現在最後一輪的比賽已經開始了,同樣,接下來由 先生來給我們介紹一下這一輪比賽的規則。
“好,大家現在看屏幕,在這一輪遊戲中,給出了一個如下所示的將 分解質因子的算法。”
- 檢查 是否是質數,假如 是質數或 則直接結束。
- 定義一個變量 ,初始值爲 。
- 檢查 是否是 的因子,假如 是 的因子,不斷將 除去 ,直到 不再是 的質因子。
- 檢查 是否是質數,假如 是質數或 ,就結束這個算法,否則將 的值加一,返回第三步。
“爲了檢驗人類智慧和人工智能之間的計算能力的差距,主辦方希望選手對區間 中的所有數都用這個算法進行分解。爲了檢驗計算的正確性,選手需要計算分解完每一個數後, 的和。特殊地,如果分解在第一步就結束了,那麼就認爲 。”
恩,謝謝 先生。大家可以看到這一道是數論方面的題目,剛纔 先生也私下和我說了,這一道題目的難度要比前兩輪的難度高很多,他認爲在短時間內,比賽雙方都無法得到準確的結果。因爲我們節目組決定與觀衆們進行互動,正在收看節目的觀衆可以關注節目跳蚤信公衆號參與解題,最快得到正確答案的觀衆將會獲得由不想跳的跳蚤不是好跳蚤——最強跳蚤跳跳跳公司提供的精美禮品一份。
作爲一名光榮的吃土少年,你立志要把這份禮品收入囊中以告別悲慘的吃土生活。然而,全世界的觀衆中也不乏人類智慧大師的存在,爲了從他們中脫穎而出,你需要以最快的速度得到這一個問題的答案。
Input
一行兩個正整數 ,表示需要分解的數的範圍
Output
輸出一行一個整數,表示每次分解結束時,變量 的值之和。
Sample Input
16 20
Sample Output
7
Solution
設 爲分解 結束時的 值,若 爲 或素數則有 ,否則 即爲 的次大素因子
假設 的取值分別爲 , 以內的素數爲 ,設 爲 中最小素因子不小於 的數字的 值之和,顯然其中的素數沒有貢獻,對於其中的合數,枚舉起最小素因子 以及其冪指數 ,那麼數字有兩種: ,其中 爲最小素因子大於 的合數,第一種對答案的貢獻爲 ,第二種對答案的貢獻爲 對答案的貢獻,進而有轉移
用 篩求出 表示 中素數個數,那麼最後一個求和即爲
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;
}