链接
http://lightoj.com/volume_showproblem.php?problem=1336
题意
t ( t ≤ 100 ) t(t\le100) t(t≤100) 次询问,每次询问 1 ∼ n ( 1 ≤ n ≤ 1 e 12 ) 1\sim n(1\le n\le 1e12) 1∼n(1≤n≤1e12) 中有多少数的正约数和是偶数。
思路
若正整数 N N N 被唯一分解为 N = p 1 c 1 p 2 c 2 ⋯ p m c m N=p_1^{c_1}p_2^{c_2}\cdots p_m^{c_m} N=p1c1p2c2⋯pmcm,其中 c i c_i ci 都是正整数, p i p_i pi 都是质数。
那么 N N N 的正约数和公式为: ( 1 + p 1 + p 1 2 + ⋯ + p 1 c 1 ) ∗ ⋯ ∗ ( 1 + p m + p m 2 + ⋯ + p m c m ) = ∏ i = 1 m ∑ j = 0 c i p i j (1+p_1+p_1^2+\cdots+p_1^{c_1})*\cdots*(1+p_m+p_m^2+\cdots+p_m^{c_m})=\prod\limits_{i=1}^{m}\sum\limits_{j=0}^{c_i}p_i^j (1+p1+p12+⋯+p1c1)∗⋯∗(1+pm+pm2+⋯+pmcm)=i=1∏mj=0∑cipij。
因为偶数 ∗ * ∗ 奇数 = = = 偶数,所以当公式中每一项都为奇数时,正约数和才为奇数。
易得:
- 当 p = 2 p=2 p=2 时, ∑ i = 0 c p i \sum\limits_{i=0}^{c}p^i i=0∑cpi 为奇数。
- 当 p ≠ 2 p\ne2 p=2 时, c c c 为偶数时, ∑ i = 0 c p i \sum\limits_{i=0}^{c}p^i i=0∑cpi 为奇数。
所以如果 N N N 的正约数和为奇数,那么公式中除 p = 2 p=2 p=2 外的每一项 c c c 都为偶数。
即 N N N 是完全平方数或 N / 2 N/2 N/2 是完全平方数。
对于 1 ∼ n 1\sim n 1∼n 中 有多少正约数和是偶数:
- 当 i ∗ i ≤ n i*i\le n i∗i≤n, i ∗ i i*i i∗i 的正约数和为奇数,共有 ⌊ n ⌋ \lfloor\sqrt{n}\rfloor ⌊n⌋ 个。
- 当 2 ∗ i ∗ i ≤ n 2*i*i\le n 2∗i∗i≤n, 2 ∗ i ∗ i 2*i*i 2∗i∗i 的正约数和为奇数,共有 ⌊ ⌊ n 2 ⌋ ⌋ \lfloor\sqrt{\lfloor\frac{n}{2}\rfloor}\rfloor ⌊⌊2n⌋⌋ 个。
所以 1 ∼ n 1\sim n 1∼n 中正约数和是偶数的个数为 n − ⌊ n ⌋ − ⌊ ⌊ n 2 ⌋ ⌋ n-\lfloor\sqrt{n}\rfloor-\lfloor\sqrt{\lfloor\frac{n}{2}\rfloor}\rfloor n−⌊n⌋−⌊⌊2n⌋⌋ 个。
代码
#include <bits/stdc++.h>
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(),(x).end()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
using namespace std;
typedef double DB;
typedef long long LL;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<PII> VPII;
//head
int main() {
//freopen("E:/OneDrive/IO/in.txt","r",stdin);
int tt;
scanf("%d",&tt);
for(int cs=1;cs<=tt;cs++) {
LL n;
scanf("%lld",&n);
printf("Case %d: %lld\n",cs,n-(LL)sqrt(n)-(LL)sqrt(n/2));
}
return 0;
}