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; }