1222 最小公倍数计数

**题目来源: Project Euler
基准时间限制:6 秒 空间限制:131072 KB 分值: 640 难度:8级算法题**
定义F(n)表示最小公倍数为n的二元组的数量。
即:如果存在两个数(二元组)X,Y(X <= Y),它们的最小公倍数为N,则F(n)的计数加1。
例如:F(6) = 5,因为[2,3] [1,6] [2,6] [3,6] [6,6]的最小公倍数等于6。

给出一个区间[a,b],求最小公倍数在这个区间的不同二元组的数量。
例如:a = 4,b = 6。符合条件的二元组包括:
[1,4] [2,4] [4,4] [1,5] [5,5] [2,3] [1,6] [2,6] [3,6] [6,6],共10组不同的组合。
Input
输入数据包括2个数:a, b,中间用空格分隔(1 <= a <= b <= 10^11)。
Output
输出最小公倍数在这个区间的不同二元组的数量。
Input示例
4 6
Output示例
10
可以推导,先考虑大小没有限制的二元组情况:

F ( n ) = i = 1 n j = 1 n [ i j g c d ( i , j ) == n ] = d | n d | i d | j [ i j d == n ] = d | n i n d j n d [ i j d == n ] = d | n i n d j n d [ i j == n d ] = d | n i = 1 d j = 1 d [ i j == d ] = d | n k | d 1

但是这种是对于二元组没有大小关系限制时的答案。
设有 d ( n ) = d | n 即因子个数函数。

现在:

i = 1 n F ( i ) = i = 1 n j | i d ( j ) = j = 1 n d ( j ) n j

我们来考虑一下

G ( n ) = i = 1 n d ( i )

那么;
G ( n ) = i = 1 d ( i ) = i = 1 n i

然后分块处理:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#define maxx 5000000
#define mod 1000000007
#define ll long long
using namespace std;

map<ll,ll>g;
ll G(ll n)
{
    if(g[n])return g[n];
    ll ans=(ll)sqrt(n);
    //while((ans+1)*(ans+1)<=n)ans++;
    for(ll i=1,last;i<=n;i=last+1)
    {
        last=n/(n/i);
        ans+=(last-i+1)*(n/i);
    }
    ans/=2;
    g[n]=ans;
    return ans;
}
map<ll,ll>f;
ll F(ll n)
{
    if(f[n])return f[n];
    ll ans=0;
    for(ll i=1,last;i<=n;i=last+1)
    {
        last=n/(n/i);
        ans+=(G(last)-G(i-1))*(n/i);
    }
    f[n]=ans;
    return ans;
}
int main()
{
    cout<<F(6)<<endl;
    ll a,b;
    cin>>a>>b;
    cout<<F(b)-F(a-1)<<endl;
    return 0;
}

但是这种推导下来,发现和实际值有出入,但是实在不知道哪里有问题,希望哪位大佬可以指出问题。

换另一种推法:

a n s ( n ) = i = 1 n j = 1 n [ i j g c d ( i , j ) <= n ? 1 : 0 ]

枚举gcd:
a n s ( n ) = d = 1 n d | i n d | j n [ g c d ( i , j ) == d ] [ i j d <= n ] = d = 1 n i = 1 n d j = 1 n d [ g c d ( i , j ) == 1 ] [ i j d <= n ]

这里可以引入欧拉函数或者莫比乌斯函数,但是欧拉函数似乎没什么用啊。
用莫比乌斯搞一下:
= d = 1 n i = 1 n d j = 1 n d k | g c d ( i , j ) μ ( k ) [ i j d <= n ] = d = 1 n k = 1 n d μ ( k ) k | i n d k | j n d [ i j d <= n ] = d = 1 n d | k n μ ( k ) i = 1 n d k j = 1 n d k [ i j k 2 d <= n ] = k = 1 n μ ( k ) d | k i = 1 n d k j = 1 n d k [ i j k 2 d <= n ]

猜你喜欢

转载自blog.csdn.net/Coldfresh/article/details/81291242