容斥. 首先考虑没平方因子的,他们对答案的贡献是1. 然后考虑至少有1个平方因子的,他们对答案的贡献是-1. 然后考虑至少有3个平方因子的,他们对答案的贡献是1…
如何快速统计一个数字有几个平方因子? 分块. 对于一个数字num,他的莫比乌斯函数代表的是不带平方数的-1的不同质数的个数次方.而num对于整个N的贡献是 $\lfloor\frac N{num^2}\rfloor$ (也就是所有区间至少包含这个平方因子的数的个数).
所以答案就是
Vibe Coding.
prompt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 帮我写一个c++代码,用于计算下面的式子:\sum_{i=1}^{\lfloor\sqrt{N}\rfloor} \left\lfloor\dfrac{N}{i^2}\right\rfloor\cdot \mu(i) 其中mu是莫比乌斯函数,N的值是2^50。 程序的思路是,首先对N开根号(下取整即可),对sqN的范围进行欧拉筛,顺带求出mu的值,然后直接枚举i统计答案。 注意开long long。 我给你一个参考欧拉筛实现: int vis[1000010];//存最小质因数,负的表示质数表中的位置(负的) int p[100010],ptop=0;//存质数 short mu[1000010];//莫比乌斯函数 void sieve(int n){//[1,n] mu[1]=1; int tmp; for(int i=2;i<=n;++i){ if(!vis[i]){ vis[i]=-(++ptop); p[ptop]=i; mu[i]=-1;// } for(int j=1;j<=ptop&&i*p[j]<=n;++j){ vis[i*p[j]]=p[j]; if(i%p[j]==0){ break; }else{ mu[i*p[j]]=-mu[i];// } } } }
Gemini 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 好的,这道题的思路很清晰。$N = 2^{50}$,所以 $\lfloor\sqrt{N}\rfloor = 2^{25}$。 我们需要筛出 $1$ 到 $2^{25}$ 范围内的莫比乌斯函数 $\mu(k)$。 $2^{25} = 33,554,432$。 你给的欧拉筛模板中的数组大小(例如 `vis[1000010]`)是不够的,需要扩大到 $2^{25}$。 同时,素数表 `p` 的大小也需要扩大。根据素数定理,$\pi(x) \approx x/\ln(x)$,$\pi(3.3 \times 10^7) \approx 3.3 \times 10^7 / 17.3 \approx 1.9 \times 10^6$。所以素数表大小开到 `2,200,000` 左右比较安全。 以下是根据你的思路和要求实现的代码: 1. **全局数组定义**:将 `vis`, `mu`, `p` 的大小调整以适应 $2^{25}$。 2. **欧拉筛 `sieve` 函数**: * 基本沿用你的实现。 * **重要**:在内层循环中,`i * p[j]` 可能会超过 `int` 的范围(尽管最终结果 `product` 不会超过 `n`,但中间计算 `i*p[j]` 时如果 `i` 和 `p[j]` 都很大,例如 $50000 \times 50000$,会先溢出再比较)。因此,`i * p[j]` 的比较和计算应使用 `long long` 来防止溢出。 * 你的代码中 `mu[i*p[j]] = 0` 的情况是依赖于全局数组默认初始化为0,这是正确的。 3. **`main` 函数**: * 定义 `N` 和 `sqN` 为 `long long` 类型。`1LL << 50` 和 `1LL << 25` 是计算它们的精确方式。 * 调用 `sieve(sqN)`。 * 循环 $k$ 从 $1$ 到 `sqN`,累加答案。 * `k` 和 `ans` 必须使用 `long long`。在计算 `(N / (k * k))` 时,`k * k` 也会非常大,所以 `k` 必须是 `long long`。 ----- ### C++ 完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 #include <iostream> const int MAX_SQRT_N = 33554432 + 10 ; const int MAX_PRIMES = 2200000 ; int vis[MAX_SQRT_N]; int p[MAX_PRIMES], ptop = 0 ; short mu[MAX_SQRT_N]; void sieve (int n) { mu[1 ] = 1 ; for (int i = 2 ; i <= n; ++i) { if (!vis[i]) { vis[i] = -(++ptop); p[ptop] = i; mu[i] = -1 ; } for (int j = 1 ; j <= ptop; ++j) { long long product = (long long )i * p[j]; if (product > n) { break ; } vis[product] = p[j]; if (i % p[j] == 0 ) { break ; } else { mu[product] = -mu[i]; } } } } int main () { long long N_VALUE = 1LL << 50 ; long long sqN_VALUE = 1LL << 25 ; sieve ((int )sqN_VALUE); long long ans = 0 ; for (long long k = 1 ; k <= sqN_VALUE; ++k) { ans += (N_VALUE / (k * k)) * mu[k]; } std::cout << ans << std::endl; return 0 ; }