平凡的函数(素数筛) 题目描述 输入 输出 样例输入 样例输出 solution code

某一天,你发现了一个神奇的函数(f(x)),它满足很多神奇的性质:

  • (f(1) = 1)
  • (f(p^c)=p igoplus c)(p)为质数,(igoplus) 为异或)
  • (f(ab) = f(a) * f(b))(a,b互质)

输入

给定(n)

输出

求出(sum_{i=1}^{n} f(i))

样例输入

23333

样例输出

171806766

solution

线性筛,然后求出当前数的最小质因子以及幂次数
对当前数质因数分解后得到的数字必定互质所以直接乘俩数的f值
剩下的就暴力乘法更新(f)数组

code

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;

inline int read(){
	int x = 0, w = 1;
	char ch = getchar();
	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return x * w;
}

const int ss = 50000010;

int f[ss], prime[ss];
bool vis[ss];
int cnt;

signed main(){
	long long ans = 1;
	f[1] = 1;
	register int n = read();
	for(register int i = 2; i <= n; i++){
		if(!vis[i]) prime[++cnt] = i, f[i] = i ^ 1;
		for(register int j = 1; i * prime[j] <= n; j++){
			vis[i * prime[j]] = 1;
			if(i % prime[j] == 0){
				register int tmp = i, c = 1;
				while(tmp % prime[j] == 0) tmp /= prime[j], ++c;
				f[i * prime[j]] = f[tmp] * (prime[j] ^ c);
				break;
			}
			f[i * prime[j]] = f[i] * f[prime[j]];
		}
		ans += f[i];
	}
	cout << ans << endl;
	return 0;
}