Processing math: 6%

2015年7月22日 星期三

[HOJ 187] 小學老師

作法:

首先觀察有哪些數字的f值會變成i,會發現這就等價於這個數是1,...,i-1的倍數,但不是i的倍數。因此可以想像10^{17}範圍內的數字的f值都不會太大,因為1,...,n的最小公倍數成長的速度非常快。可以預處理出最大的f值只會到41,因此對於所求的值,對於每一項L(i)來說,可以先把他換成L(f(i))+1,這樣就只需要知道[A,B]之間有幾個數的f值等於i了(i=1,...,41),而這顯然用前面的等價條件就可以算了。

code :



#include<bits/stdc++.h>
#define LL long long
using namespace std;
 
inline LL cal(LL a,LL b)
{
    return a/b ;
}
int f[50],lo[50] ;
LL lcm[50] ;
main()
{
    lcm[1]=1 ; lcm[2]=2 ;
    f[2]=1 ; lo[2]=1 ;
    for(int i=3;i<=41;i++)
    {
        lcm[i]=lcm[i-1]/__gcd(lcm[i-1],(LL)i)*i ;
        for(int j=2;;j++) if(i%j)
            {f[i]=j ; break ;}
        lo[i]=lo[f[i]]+1 ;
    }
    LL a,b ;
    while(scanf("%lld%lld",&a,&b)!=EOF)
    {
        LL ans=0 ;
        for(int i=2;i<=41;i++)
        {
            LL num=cal(b,lcm[i-1])-cal(b,lcm[i]) ;
            num-=cal(a-1,lcm[i-1])-cal(a-1,lcm[i]) ;
            ans+=num*lo[i] ;
        }
        printf("%lld\n",ans+b-a+1) ;
    }
}
 

沒有留言:

張貼留言