题解:P14640 【OIMO Round 1】校验
zhang__yi__cheng · · 题解
P14640 【OIMO Round 1】校验
题目大意
- 正整数
x 的校验值:(-1)^{\Omega(x)} (\Omega(x) 表示x 的可重素因子个数,例如\Omega(12)=\Omega(2×2×3)=3 ,校验值为-1 ); - 数
n 的喜爱度:n 所有因数的校验值之和,即f(n) = \sum\limits_{d\mid n} (-1)^{\Omega(d)} ; - 问题要求:给定
T 组查询区间[l,r] ,求区间内所有数的喜爱度之和\sum\limits_{i=l}^r f(i) 。
基本思路
核心是简化
- 对
n 素因数分解n = p_1^{k_1}p_2^{k_2}\dots p_m^{k_m} ,其因数d = p_1^{a_1}p_2^{a_2}\dots p_m^{a_m} (0\le a_i\le k_i ); - 校验值满足乘积性:
(-1)^{\Omega(d)} = \prod\limits_{i=1}^m (-1)^{a_i} ,因此f(n) = \prod\limits_{i=1}^m \sum\limits_{a_i=0}^{k_i} (-1)^{a_i} ; - 单素因子项求和:
\sum\limits_{a=0}^k (-1)^a ,若k 为偶数则和为1 ,若k 为奇数则和为0 ; - 最终结论:
f(n)=1 当且仅当n 是完全平方数(所有素因子指数为偶数),否则f(n)=0 。
AC 代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll int_sqrt(ll x) {
if (x < 0) return 0;
ll k = ll(sqrtl(x));
while ((k + 1) * (k + 1) <= x) k++;
while (k * k > x) k--;
return k;
}
int T;
ll l, r;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> T;
while (T--) {
cin >> l >> r;
ll cnt_r = int_sqrt(r);
ll cnt_l_1 = int_sqrt(l - 1);
cout << (cnt_r - cnt_l_1) << '\n';
}
return 0;
}