首先觀察有哪些數字的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) ; } }
沒有留言:
張貼留言