LightOJ1336(约数和)

题意: 求出 n n 以内约数之和为偶数的数的个数。
数据范围: n 1 0 12 n\leq 10^{12}

题解: 一个数的约数和公式:
由于 n = p 1 α 1 p 2 α 2 p 3 α 3 . . . p k α k n=p_1^{\alpha_1}p_2^{\alpha_2}p_3^{\alpha_3}...p_k^{\alpha_k}
所以 σ ( n ) = ( 1 + p 1 + p 1 2 + . . . + p 1 α 1 ) . . . ( 1 + p k + p k 2 + . . . + p k α k ) \sigma(n)=(1+p_1+p_1 {}^2+...+p_1{}^{\alpha_1})...(1+p_k+p_k {}^2+...+p_k{}^{\alpha_k})
= p 1 α 1 1 p 1 1 . . . p k α k 1 p k 1 =\frac{p_1{}^{\alpha_{1}}-1}{p_{1}-1}...\frac{p_k{}^{\alpha_{k}}-1}{p_{k}-1}

  • 对于 2 2 ,存在则形成奇数贡献。
  • 对于奇素数,只有 α i \alpha_i 为奇数时, p i p_i 的贡献才为偶数。

由于形成偶数的条件太多了,即只要存在一个偶数贡献即可,反向思考形成奇数的条件为所有部分都要为奇数,而形成奇素数贡献为奇数的条件为 α i \alpha_i 为偶数,奇素数的幂为偶数其必然为完全平方数。
所以直接考虑所有的完全平方数即可,至于考虑 2 2 的影响则直接完全平方数乘 2 2 即可,只需乘一个 2 2 因为乘两个 2 2 还是完全平方数。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e6 + 10;

int b_s(ll x) {
	int l = 1, r = N - 1;
	while(l < r) {
		int mid = l + r + 1 >> 1;
		if(1ll * mid * mid <= x) l = mid;
		else r = mid - 1;
	}
	return l;
}

int main()
{
	int T; scanf("%d", &T);
	for(int k = 1; k <= T; ++k) {
		ll n; scanf("%lld", &n);
		int r = b_s(n);
		
		int res = r;
		for(int i = 1; i <= r; ++i) {
			if(1ll * i * i * 2 <= n) ++res;
			else break;
		}
		printf("Case %d: %lld\n", k, n - res);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43900869/article/details/107591686