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