zjnu1757Excellent (數學公式)

Description

Let us begin with a positive integer N and find the smallest positive integer which doesn't divide N. If we repeat the procedure with the resulting number, then again with the 

new result and so on, we will eventually obtain the number 2 (two). Let us define strength(N) as the length of the resulting sequence. 

For example, for N = 6 we obtain the sequence 6, 4, 3, 2 which consists of 4 numbers, thus strength(6) = 4. 

Given two positive integers A < B, calculate the sum of strengths of all integers between A and B (inclusive), that is, strength(A) + strength(A + 1) + ... + strength(B).

Input

The first and only line of input contains two positive integers, A and B (3 ≤ A < B < 10^17). 

Output

The first and only line of output should contain the requested sum of strengths.

Sample Input

3 6 100 200

Sample Output

11

262

題意:一個數按如下方法得到一個序列,即每一次找到最小的不整除它的數,然後再把找到的數當做這個數,一次循環下去,直到變爲2,產生的序列組成的長度即爲這一個數的強度,現在給你兩個數A,B,問[A,B]這個區間內的所有數的強度和是多少。

思路:我們打表可以發現,10^7內的數第一個最小的不整除它的數都很小,最大爲47,所以我們可以算出這個區間內第一個不整除的數爲2,3,4,5...47的數的個數,然後乘上2,3,..47的強度累加起來就可以了。那麼現在要做的就是怎麼算區間內第一個不整除的數爲x的個數,可以觀察得到,要使得第一個不整除的數爲x,那麼這個數一定要整除1,2,...x-1,即lcm(1,...x-1),但是這個數又不能整除x,所以要在這些數中減去整除x的數的個數,即減去能整除lcm(1,....x)的數的個數。對於一個區間[A,B],能整除k的數的個數是B/k-(A-1)/k,所以就可以算出來了。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
ll zhi[100]={0,2,3,4,5,7,8,9,11,13,16,17,19,23,25,27,29,31,32,37,41};
ll stg[100]={0,1,2,3,2,2,3,2 ,2 ,2 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,3 ,2 ,2};
ll num1[20],num2[20];
ll gs[100];
ll gcd(ll a,ll b){
    return b ? gcd(b,a%b) : a;
}
void init()
{
    ll i,j;
    gs[1]=1;
    for(i=2;i<=42;i++){
        gs[i]=gs[i-1]/gcd(gs[i-1],i)*(ll)i;
    }
}

int main()
{
    ll n,m;
    int i,j;
    init();
    while(scanf("%lld%lld",&m,&n)!=EOF)
    {
        ll sum=0;
        for(i=1;i<=20;i++){
            sum+=(n/gs[zhi[i]-1 ]-(m-1)/gs[zhi[i]-1 ]-( n/gs[zhi[i]]-(m-1)/gs[zhi[i] ] ) )*(stg[i]+1);
        }
        printf("%lld\n",sum);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章