ACM-ICPC 2018 徐州赛区网络预赛 D.Easy Math
题目链接
https://nanti.jisuanke.com/t/A2003
题目大意
求 $\sum\limits_{i=1}^m{\mu(in)}$
题目分析
显然可以将 $n$ 提取出来,则有 $\mu(n)\sum\limits_{i=1}^m{\mu(i)[(i, n) = 1]}$ 。
考虑使用 min_25 筛来解决问题,只需要在预处理的时候把所有 $n$ 的质因子去除即可。然后在筛的时候按照真实的函数计算即可。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = 1e5 + 5;
int N = 1e5;
long long mod = 1e9 + 7;
long long n, m;
long long prime[maxn];
bool isnp[maxn];
long long p[maxn];
int pc = 0;
int id[maxn];
int id2[maxn];
int w[maxn];
int wc;
long long h[maxn];
long long g[maxn];
vector <long long> vec;
int Mu(long long x) {
int ret = 1;
long long t = x;
for(long long d=2;d*d<=t;d++){
if(x % d == 0) {
x /= d;
if(x % d == 0){
return 0;
}else{
ret *= -1;
}
}
}
if(x!=1) {
ret *= -1;
}
return ret;
}
int getfactor(long long x) {
long long t = x;
for(long long d=2;d*d<=t;d++){
if(x % d == 0) {
vec.push_back(d);
while(x % d == 0)x /= d;
}
}
if(x != 1){
vec.push_back(x);
}
return 0;
}
int getid(long long x){
if(x <= N){
return id[x];
}else{
return id2[n / x];
}
}
long long F(int b, int x){
return (x == 1 and m % b) ? -1 : 0;
}
int init(){
long long i, j;
for(i=2;i<=N;i++){
if(!isnp[i]){
pc++;
prime[pc] = i;
p[pc] = p[pc - 1] + F(i, 1);
}
for(j=1;j<=pc and i * prime[j]<=N;j++){
isnp[i * prime[j]] = true;
if(i % prime[j] == 0){
break;
}
}
}
return 0;
}
long long qpow(long long b, long long x){
long long ret = 1;
while(x){
if(x & 1){
ret = ret * b % mod;
}
b = b * b % mod;
x >>= 1;
}
return ret;
}
int pre(){
long long i, j;
for(i=1;i<=n;i=j+1){
j = n / (n / i);
w[++wc] = n / i;
if(w[wc] <= N){
id[w[wc]] = wc;
}else{
id2[n / w[wc]] = wc;
}
g[wc] = w[wc] - 1;
}
for(j=1;j<=pc;j++){
for(i=1;i<=wc and 1ll*prime[j]*prime[j]<=w[i];i++){
int k = getid(w[i] / prime[j]);
g[i] -= g[k] - (j - 1);
}
}
for(i=1;i<=wc;i++){
g[i] = g[i] - (long long)(upper_bound(vec.begin(), vec.end(), w[i]) - vec.begin());
}
return 0;
}
long long sum(long long x, long long i){
if(x <= 1 or prime[i] > x)return 0;
int k = getid(x);
long long ret = -(g[k] + p[i - 1]);
for(int j=i;j<=pc and prime[j]*prime[j]<=x;j++){
for(long long e=1,r=prime[j];r*prime[j]<=x;e++,r*=prime[j]){
ret += F(prime[j], e) * sum(x / r, j + 1) + F(prime[j], e + 1);
}
}
return ret;
}
int main(){
int i, j;
cin >> n >> m;
N = sqrt(n);
getfactor(m);
init();
pre();
cout << Mu(m) * (sum(n, 1) + 1) << endl;
return 0;
}