平凡的函数(素数筛)
题目描述
某一天,你发现了一个神奇的函数\(f(x)\),它满足很多神奇的性质:
- \(f(1) = 1\)
- \(f(p^c)=p \bigoplus c\)(\(p\)为质数,\(\bigoplus\) 为异或)
- \(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;
}
风吹过,我来过~