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;
}


你可能感兴趣的:(数学公式)