【NOI2017模拟3.19】Sum

Description:

【NOI2017模拟3.19】Sum_第1张图片
n < = 1 e 10 n<=1e10 n<=1e10

题解:

f [ i ] = ∑ j = 1 i ∑ k = 1 i [ ( i , j ) , ( i , k ) ] f[i]=\sum_{j=1}^i\sum_{k=1}^i[(i,j),(i,k)] f[i]=j=1ik=1i[(i,j),(i,k)]

不难(才怪)想到 f [ i ] f[i] f[i]是一个积性函数。

如何快速感性证明:
我们知道 g c d 、 l c m gcd、lcm gcdlcm都是和每个质因子的指数有关,每一个质因子互不影响,对于这个题显然就是直接乘起来。

然后就是考虑 p k p^k pk怎么做,即枚举 l c m lcm lcm的大小,然后随便写写。
f ( p k ) f(p^k) f(pk)
= ( ∑ i = 0 k − 1 p i ∗ ( p k − p k − i − 1 ) 2 ∗ ( p k − p k − i ) 2 ) + p k ∗ ( 2 ∗ p k − 1 ) =(\sum_{i=0}^{k-1}p^i*(p^k-p^{k-i-1})^2*(p^k-p^{k-i})^2)+p^k*(2*p^k-1) =(i=0k1pi(pkpki1)2(pkpki)2)+pk(2pk1)
= ( 2 ∗ k + 1 ) ∗ ( p 2 k − p 2 k − 1 ) + p k − 1 =(2*k+1)*(p^{2k}-p^{2k-1})+p^{k-1} =(2k+1)(p2kp2k1)+pk1

有了这个套个min_25就好了。

Code:

#include
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i <  B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
#define ui unsigned int
using namespace std;

const int N = 2e5 + 5;

ll n;
ll w[N]; int sqr, m, i1[N], i2[N];
int bz[N], p[N]; ui sp[3][N];
ui g[3][N];

#define num(A) ((A) <= sqr ? i1[A] : i2[n / (A)])

void sieve(int n) {
	fo(i, 2, n) {
		if(!bz[i]) p[++ p[0]] = i;
		for(int j = 1; i * p[j] <= n; j ++) {
			bz[i * p[j]] = 1;
			if(i % p[j] == 0) break;
		}
	}
	fo(i, 1, p[0]) {
		ui s = 1;
		fo(j, 0, 2) {
			sp[j][i] = sp[j][i - 1] + s;
			s *= p[i];
		}
	}
}

ui calc2(ll n) {
	if(n & 1) return (ui)((n + 1) / 2) * n;
	return (ui) (n / 2) * (n + 1);
}
ui calc3(ll n) {
	ll a[3]; a[0] = n; a[1] = n + 1; a[2] = 2 * n + 1;
	fo(i, 0, 2) if(a[i] % 2 == 0) { a[i] /= 2; break;}
	fo(i, 0, 2) if(a[i] % 3 == 0) { a[i] /= 3; break;}
	return (ui) a[0] * (ui) a[1] * (ui) a[2];
}

ui dg(ll x, int j) {
	if(x <= 1 || p[j] > x) return 0;
	ui s = g[2][num(x)] * 3 - g[1][num(x)] * 3 + g[0][num(x)];
	s -= sp[2][j - 1] * 3 - sp[1][j - 1] * 3 + sp[0][j - 1];
	for(int k = j; k <= p[0] && (ll) p[k] * p[k] <= x; k ++) {
		ll p1 = p[k], p2 = p1 * p1;
		ui p3 = 1, p4 = p[k], p5 = p4 * p4, sp = p5, e = 3;
		for(; p2 <= x; p1 = p2, p2 *= p[k], e += 2) {
			ui f = (p5 - p4) * e + p3;
			ui nf = ((p5 - p4) * sp * (e + 2) + p3 * (ui) p[k]);
			s += f * dg(x / p1, k + 1) + nf;
			p3 = p3 * (ui) p[k];
			p4 = p4 * sp;
			p5 = p5 * sp;
		}
	}
	return s;
}

int main() {
	freopen("sum.in", "r", stdin);
	freopen("sum.out", "w", stdout);
	scanf("%lld", &n);
	sqr = sqrt(n);
	sieve(sqr);
	for(ll i = 1, j; i <= n; i = j + 1) {
		j = n / (n / i); w[++ m] = n / i;
		if(w[m] <= sqr) i1[w[m]] = m; else i2[n / w[m]] = m;
		g[0][m] = (ui) w[m] - 1;
		g[1][m] = calc2(w[m]) - 1;
		g[2][m] = calc3(w[m]) - 1;
	}
	for(int j = 1; j <= p[0]; j ++) {
		for(int i = 1; i <= m && (ll) p[j] * p[j] <= w[i]; i ++) {
			int k = num(w[i] / p[j]);
			ui s = 1;
			fo(t, 0, 2) {
				g[t][i] -= s * (g[t][k] - sp[t][j - 1]);
				s *= p[j];
			}
		}
	}
	pp("%u\n", dg(n, 1) + 1);
}

你可能感兴趣的:(筛)