求a[gcd(i,j)]之和

给定长度为 N N 的数组 a ,求

1in,1jma[gcd(i,j)] ∑ 1 ≤ i ≤ n , 1 ≤ j ≤ m a [ g c d ( i , j ) ]

数据范围: 1n,mN105 1 ≤ n , m ≤ N ≤ 10 5

f(n,m)=i=1nj=1ma[gcd(i,j)]=d=1min(n,m)i=1nj=1ma[d]×[gcd(i,j)==d]=d=1min(n,m)a[d]×i=1ndj=1md[gcd(i,j)==1] f ( n , m ) = ∑ i = 1 n ∑ j = 1 m a [ g c d ( i , j ) ] = ∑ d = 1 m i n ( n , m ) ∑ i = 1 n ∑ j = 1 m a [ d ] × [ g c d ( i , j ) == d ] = ∑ d = 1 m i n ( n , m ) a [ d ] × ∑ i = 1 n d ∑ j = 1 m d [ g c d ( i , j ) == 1 ]

先知道莫比乌斯函数的定义:
d|nμ(d)=1 n=1d|nμ(d)=0 n>1 ∑ d | n μ ( d ) = 1   ( 当 n = 1 ) ∑ d | n μ ( d ) = 0   ( 当 n > 1 )


g(n,m)=i=1nj=1m[gcd(i,j)==1]=i=1nj=1md|gcd(i,j)μ(d)=d=1min(n,m)μ(d)×nd×md g ( n , m ) = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) == 1 ] = ∑ i = 1 n ∑ j = 1 m ∑ d | g c d ( i , j ) μ ( d ) = ∑ d = 1 m i n ( n , m ) μ ( d ) × n d × m d


f(n,m)=d=1min(n,m)a[d]×g(nd,md) f ( n , m ) = ∑ d = 1 m i n ( n , m ) a [ d ] × g ( n d , m d )

复杂度计算: ni=1niO(nlogn) ∑ i = 1 n n i ≈ O ( n l o g n )

美团的笔试题给定了A数组,即 a1=p,ai=(ai+153)%p a 1 = p , a i = ( a i + 153 ) % p
代码如下:

#include <bits/stdc++.h>
using namespace std;
int a[100007],mu[100007];
using ll = long long;
ll g(int n, int m)
{
    ll ret = 0;
    for(int i=1; i<=min(n, m); ++i)
        ret+=(ll)mu[i]*(n/i)*(m/i);
    return ret;
}
int main()
{
    int N,n,m,p;
    scanf("%d%d%d%d",&N,&n,&m,&p);
    ll ans = 0;
    mu[1]=1;
    for(int i=1; i<=N; ++i)
        for(int j=2*i;j<=N;j+=i)
            mu[j]-=mu[i];
    a[1]=p;
    for(int i=2; i<=N; ++i)
        a[i]=(a[i-1]+153)%p;
    for(int i=1; i<=min(n, m); ++i)
    {
        ans+=(ll)a[i]*g(n/i,m/i);
    }
    cout << ans << '\n';
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值