ICPC2018 沈阳网络赛 C.Convex Hull

ICPC2018 沈阳网络赛 C.Convex Hull

题目链接

https://nanti.jisuanke.com/t/A1991

题目大意

定义 $gay(i)$ 函数在 $i$ 含有平方因子时为 $0$ ,否则为 $i ^ 2$

你需要计算:

$$\sum\limits_{num=1}^n (\sum\limits_{i=1}^{num} gay(i)) \mod p $$

题目分析

首先可以将这个函数进行化简,化简为

$$\sum\limits_{i=1}^n\sum\limits_{j=1}^i\mu^2(j)j ^ 2$$

换为考虑统计每个数出现的次数,那么可以化为

$$\sum\limits_{i=1}^n\mu^2(i)i ^ 2(n – i + 1)$$

展开可以得到

$$\sum\limits_{i=1}^n((n + 1)\mu^2(i)i ^ 2 – \mu^2(i)i ^ 3)$$

再考虑求$\sum\limits_{i=1}^n\mu^2(i)i ^ 2$

使用容斥将所有的平方因子都去掉即可,容斥因子显然为 $\mu(i)$

因此可化为

$$\sum\limits_{i=1}^{\sqrt{n}}\mu(i)\sum\limits_{j=1}^{\lfloor\frac{n}{i ^ 2}\rfloor}(ji^2)^2$$

$$\sum\limits_{i=1}^{\sqrt{n}}\mu(i)i^4\sum\limits_{j=1}^{\lfloor\frac{n}{i ^ 2}\rfloor}j^2$$

同理 $i^3$ 的式子也可以这样处理,得到

$$\sum\limits_{i=1}^{\sqrt{n}}\mu(i)i^6\sum\limits_{j=1}^{\lfloor\frac{n}{i ^ 2}\rfloor}j^3$$

用平方和及立方和公式求和即可。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <unordered_map>

using namespace std;

const int maxn = 1e5 + 5;
const int m = 1e5;

long long n, k, p;

int prime[maxn];
bool isnp[maxn];
long long u[maxn];
long long f[maxn];
long long g[maxn];
int pc = 0;

long long mul(__int128 x, __int128 y){
	return x * y % p;
	//如果用下面注释里面的会 TLE……
	/*long long ret = 0;
	long long k = x / 10000000ll;
	ret = (ret + 10000000ll * y % p * k) % p;
	x %= 10000000ll;
	ret = (ret + x * y) % p;
	return ret;*/
}

int init(){
	int i, j;
	
	u[1] = 1;
	
	for(i=2;i<=m;i++){
		if(!isnp[i]){
			pc++;
			prime[pc] = i;
			u[i] = -1;
		}
		
		for(j=1;j<=pc and i * prime[j]<=m;j++){
			isnp[i * prime[j]] = true;
			if(i % prime[j] == 0){
				u[i * prime[j]] = 0;
				break;
			}else{
				u[i * prime[j]] = -u[i];
			}
		}
	}
	
	return 0;
}

long long suma(long long x){
	long long ret = f[x];
	x = n / x / x;
	long long a = x, b = x + 1, c = 2 * x + 1;
	
	if(a % 2 == 0){
		a /= 2;
	}else if(b % 2 == 0){
		b /= 2;
	}else{
		c /= 2;
	}
	
	if(a % 3 == 0){
		a /= 3;
	}else if(b % 3 == 0){
		b /= 3;
	}else{
		c /= 3;
	}
	
	ret = mul(mul(ret, a), mul(b, c));
	
	return ret;
}

long long sumb(long long x){
	long long ret = g[x];
	x = n / x / x;
	long long a = x, b = x + 1;
	
	if(a % 2 == 0){
		a /= 2;
	}else{
		b /= 2;
	}
	
	ret = mul(ret, mul(mul(a, a), mul(b, b)));
	
	return ret;
}

int main(){
	long long i, j;
	long long ans = 0;
	
	init();
	
	while(~scanf("%lld%lld", &n, &p)){
		ans = 0;
	
		for(i=1;i*i<=n;i++){
			f[i] = u[i] * mul(mul(i, i), mul(i, i));
			g[i] = u[i] * mul(mul(mul(i, i), mul(i, i)), mul(i, i));
		}
		
		for(i=1;i*i<=n;i++){
			ans = (ans + (mul(n + 1, suma(i)) - sumb(i)) % p + p) % p;
		}
		printf("%lld\n", ans);
	}
	
	return 0;
}

发表回复

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

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