CodeForces 1717E【线性筛】

本文介绍了如何使用埃拉托斯特尼筛法求解给定整数n下,满足a+b+c=n且lcm(gcd(a,b),c)的三元组(a,b,c)的和。通过枚举gcd(a,b)和a+b的组合,并利用欧拉函数计算可能的组合数量,实现了高效的算法实现。
摘要由CSDN通过智能技术生成

题意:给定 n n n,求所有三元组 ( a , b , c ) (a,b,c) (a,b,c) 满足 a + b + c = n a+b+c=n a+b+c=n lcm ⁡ ( gcd ⁡ ( a , b ) , c ) \operatorname{lcm}(\gcd(a,b),c) lcm(gcd(a,b),c) 的和。

思想:

第一层循环枚举 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b) 的值。

然后枚举 a + b a+b a+b 的值。

容易发现, a + b a + b a+b 的值一定是 k × gcd ⁡ ( a , b ) k\times \gcd (a,b) k×gcd(a,b) k ∈ N ∗ k\in N^* kN

也就是说, ( a , b ) (a,b) (a,b) 的取值方法一共有 φ ( ⌊ n − c gcd ⁡ ( a , b ) ⌋ ) \varphi(\lfloor\frac{n-c}{\gcd(a,b)}\rfloor) φ(⌊gcd(a,b)nc⌋) 种,所以考虑进行类似于埃式筛法的算法,每一次更新的时候将答案加上 lcm ⁡ ( gcd ⁡ ( a , b ) , c ) × φ ( ⌊ n − c gcd ⁡ ( a , b ) ⌋ ) \operatorname{lcm}(\gcd(a,b),c)\times \varphi(\lfloor\frac{n-c} {\gcd(a,b)}\rfloor) lcm(gcd(a,b),c)×φ(⌊gcd(a,b)nc⌋) 即可。

// 这回只花了45min就打完了。
// 真好。记得多手造几组。最好有暴力对拍。

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int N = 2e5 + 10, mod = 1e9 + 7;
int phi[N]; // debug 这个地方要开 long long
bool not_prime[N];
int cnt, primes[N], n, ans = 0;

void sieve()
{
  phi[1] = 1;
  for (int i = 2; i < N; i ++)
  {
    if (!not_prime[i])
    {
      primes[++ cnt] = i;
      phi[i] = i - 1;
    }
    for (int j = 1; i * primes[j] < N; j ++)
    {
      not_prime[i * primes[j]] = true; // debug i*primes[j] --> j*primes[j]
      if (i % primes[j])
        phi[i * primes[j]] = phi[i] * (primes[j] - 1);
      else
      {
        phi[i * primes[j]] = phi[i] * primes[j];
        break;
      }
    }
  }
}

signed main()
{
  cin >> n;
  sieve();
  for (int i = 1; i < n; i ++)
    for (int j = 2 * i; j < n; j += i) // debug =n 的话没有法子选了
      (ans += phi[j / i] * lcm(i, n - j) % mod) %= mod;
  cout << ans << '\n';
  return 0;
}

// 足下千里,移步换景,寰宇纷呈万花筒

凑字数凑字数凑字数凑字数
凑字数凑字数凑字数凑字数
凑字数凑字数凑字数凑字数
凑字数凑字数凑字数凑字数
凑字数凑字数凑字数凑字数
凑字数凑字数凑字数凑字数
凑字数凑字数凑字数凑字数
凑字数凑字数凑字数凑字数
凑字数凑字数凑字数凑字数
凑字数凑字数凑字数凑字数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值