【51nod 1227】 平均最小公倍数(杜教筛)

计算F(a,b)算法
本文介绍了一种计算特定函数F(a,b)的高效算法,该函数涉及最小公倍数和最大公约数的概念,并通过杜教筛算法优化计算过程。

题目来源: Project Euler
基准时间限制:1.5 秒 空间限制:131072 KB 分值: 640 难度:8级算法题 重点内容
Lcm(a,b)表示a和b的最小公倍数,A(n)表示Lcm(n,i)的平均数(1 <= i <= n),
例如:A(4) = (Lcm(1,4) + Lcm(2,4) + Lcm(3,4) + Lcm(4,4)) / 4 = (4 + 4 + 12 + 4) / 4 = 6。
F(a, b) = A(a) + A(a + 1) + …… A(b)。(F(a,b) = ∑A(k), a <= k <= b)
例如:F(2, 4) = A(2) + A(3) + A(4) = 2 + 4 + 6 = 12。
给出a,b,计算F(a, b),由于结果可能很大,输出F(a, b) % 1000000007的结果即可。
Input
输入2个数a,b,中间用空格分隔(1 <= a <= b <= 10^9)。
Output
输出F(a, b) % 1000000007的结果。
Input示例
1 100
Output示例
122726

推吧。我们先看A(n)A(n).

A(n)=1ni=1nlcm(i,n)=i=1igcd(i,n)A(n)=1n∑i=1nlcm(i,n)=∑i=1igcd(i,n)

我们枚举gcd:
A(n)=d|nd|i[gcd(i,n)==d]id=d|nd|i[gcd(id,nd)==1]id=d|nind[gcd(i,nd)==1]iA(n)=∑d|n∑d|i[gcd(i,n)==d]id=∑d|n∑d|i[gcd(id,nd)==1]id=∑d|n∑ind[gcd(i,nd)==1]i

这里可以引入欧拉函数了:
A(n)=12+d|ndϕ(d)2A(n)=12+∑d|ndϕ(d)2

设:

F(n)=n2+12i=1nj|ijϕ(j)F(n)=n2+12∑i=1n∑j|ijϕ(j)

设:
F(n)=i=1nj|ijϕ(j)=j=1njϕ(j)njF′(n)=∑i=1n∑j|ijϕ(j)=∑j=1njϕ(j)⌊nj⌋

这里就很显然了,用杜教筛搞jϕ(j)jϕ(j)的前缀和,然后分块求答案。
f(x)=xϕ(x),g(x)=xf(x)=xϕ(x),g(x)=x,这两个函数搞一下卷积。

fg(n)=d|ndϕ(d)nd=n2f∗g(n)=∑d|ndϕ(d)nd=n2

sum(n)=i=1niϕ(i)sum(n)=∑i=1niϕ(i)

推得:

sum(n)=(n+1)n(2n+1)6i=2nisum(ni)sum(n)=(n+1)n(2n+1)6−∑i=2ni∗sum(⌊ni⌋)

代码:

#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;
bool isP[maxx];
int prime[400000];
int cnt;
ll phi[maxx];
ll sum[maxx];
ll inv2=500000004,inv6=166666668;
void init()
{
    phi[1]=1;
    for(int i=2;i<maxx;i++)
    {
        if(!isP[i])
        {
            prime[cnt++]=i;
            phi[i]=i-1;
        }
        for(int j=0;j<cnt&&(ll)i*prime[j]<maxx;j++)
        {
            isP[i*prime[j]]=true;
            if(i%prime[j])
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
            else
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
        }
    }
    for(int i=1;i<maxx;i++)
        sum[i]=i*phi[i]%mod;
    for(int i=1;i<maxx;i++)
        sum[i]=(sum[i]+sum[i-1])%mod;
}
map<ll,ll>M;
ll get(ll a,ll b)
{
    return (b-a+1)*(b+a)%mod*inv2%mod;
}
ll work(ll x)
{
    if(x<maxx)return sum[x];
    if(M[x])return M[x];
    ll t=x%mod;
    ll ans=t*(t+1)%mod*(2*t%mod+1)%mod*inv6%mod;
    for(ll i=2,last;i<=x;i=last+1)
    {
        last=x/(x/i);
        ans=(ans-get(i,last)*work(x/i)%mod)%mod;
    }
    if(ans<0)ans=(ans+mod)%mod;
    M[x]=ans;
    return ans;
}
ll F(ll x)
{
    ll ans=0;
    for(ll i=1,last;i<=x;i=last+1)
    {
       last=x/(x/i);
       ll now=(work(last)-work(i-1)+mod)%mod;
       ll base=x/i%mod;
       ans=(ans+base*now%mod)%mod;
    }
    ans=ans*inv2%mod;
    ans=(ans+x*inv2%mod)%mod;
    return ans;
}
int main()
{
    init();
    ll a,b;
    cin>>a>>b;
    cout<<(F(b)-F(a-1)+mod)%mod<<endl;
    return 0;
}
目前没有关于51nod 3478题目的具体描述和官方公布的C++解决方案代码。以下是一种通用的解题思路以及一个示例C++代码模板,可以用于解决类似的问题。 ### 问题解题思路 51nod 3478通常可能涉及以下算法或技术: - 动态规划(DP)或状态转移方程 - 贪心算法 - 数据结构(如线段树、堆、优先队列等) - 图论算法(如最短路径、最小生成树等) ### 示例C++代码模板 以下是一个通用的C++代码框架,适用于需要读取输入并处理大规模数据的问题: ```cpp #include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 100005; // 根据题目规模调整 int n; ll k; ll a[MAXN]; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> k; for (int i = 1; i <= n; ++i) { cin >> a[i]; a[i] += a[i - 1]; // 前缀和 } // 示例逻辑:查找是否存在和为k的连续子数组 unordered_map<ll, int> prefix_map; prefix_map[0] = 0; for (int i = 1; i <= n; ++i) { if (prefix_map.find(a[i] - k) != prefix_map.end()) { cout << prefix_map[a[i] - k] + 1 << " " << i << endl; return 0; } prefix_map[a[i]] = i; } cout << "No Solution" << endl; return 0; } ``` ### 说明 - 上述代码使用了前缀和和哈希表(`unordered_map`)来高效查找是否存在和为`k`的连续子数组。 - 时间复杂度为O(n),适用于大规模输入。 - 如果题目有其他特定要求,可以根据具体条件修改代码逻辑。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值