ACM-ICPC 2018 徐州赛区网络预赛 D.Easy Math

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

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据