题解 肯德基

传送门

首先 \(\mu^2(i)=\sum\limits_{d^2|i}\mu(i)\)
于是

\[\sum\limits_{i=1}^n f(i) = \sum\limits_{d=1}^{\sqrt{n}}\mu(d)*d^2*s(\lfloor \frac{n}{d^2} \rfloor) \]

其中

\[s(n)=\frac{n*(n+1)}{2} \]

于是这个东西直接求是 \(O(T\sqrt n)\) 的,可以有80pts
来康康怎么优化,发现 \(\lfloor \frac{n}{d^2} \rfloor\) 这个东西是 \(\sqrt[3] n\) 级别的
证明一下
\(d\leqslant n^{\frac{1}{3}}\) 时,\(d\) 只有 \(\sqrt[3]{n}\) 种取值
\(d > n^{\frac{1}{3}}\) 时,有 \(d^2 > n^{\frac{2}{3}}\) ,所以 \(\lfloor \frac{n}{d^2} \rfloor\) 只有 \(\sqrt[3]{n}\) 种取值
得证
于是这里要对 \(\lfloor \frac{n}{d^2} \rfloor\) 整除分块,这个怎么做呢?

于是最终复杂度 \(O(\sqrt n + T\sqrt[3]{n})\)

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 10000010
#define ll long long
#define ull unsigned long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
inline ll read() {
	ll ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

ll n;
int pri[N], pcnt, mu[N];
bool npri[N];

namespace force{
	void solve() {
		int T=read();
		while (T--) {
			n=read();
			ull ans=0;
			for (int i=1; i<=n; ++i) if (mu[i]) ans+=i;
			printf("%llu\n", ans);
		}
		exit(0);
	}
}

namespace task1{
	inline ull sum(ull n) {
		if (n&1) return ((n+1)/2)*n;
		else return (n/2)*(n+1);
		// return n*(n+1)/2;
	}
	void solve() {
		int T=read();
		while (T--) {
			n=read();
			ull ans=0; ll lim=sqrt(n);
			for (ll i=1; i<=lim; ++i) if (mu[i]) {
				ans+=1llu*mu[i]*i*i*sum(n/(i*i));
			}
			printf("%llu\n", ans);
		}
		exit(0);
	}
}

namespace task2{
	int tot1, tot2;
	ll buc1[N], buc2[N];
	inline ull sum(ull n) {
		if (n&1) return ((n+1)/2)*n;
		else return (n/2)*(n+1);
		// return n*(n+1)/2;
	}
	void solve() {
		for (int i=1; i<N; ++i)
			if (mu[i]==1) buc1[++tot1]=i;
			else if (mu[i]==-1) buc2[++tot2]=i;
		int T=read();
		while (T--) {
			n=read();
			ull ans=0; ll lim=sqrt(n);
			for (int i=1; i<=tot1&&buc1[i]*buc1[i]<=n; ++i) ans+=1llu*buc1[i]*buc1[i]*sum(n/(buc1[i]*buc1[i]));
			for (int i=1; i<=tot2&&buc2[i]*buc2[i]<=n; ++i) ans+=-1llu*buc2[i]*buc2[i]*sum(n/(buc2[i]*buc2[i]));
			printf("%llu\n", ans);
		}
		exit(0);
	}
}

namespace task{
	ull sum[N];
	inline ull qsum(ull n) {
		if (n&1) return ((n+1)/2)*n;
		else return (n/2)*(n+1);
	}
	void solve() {
		for (int i=1; i<N; ++i) sum[i]=sum[i-1]+1llu*mu[i]*i*i;
		int T=read();
		while (T--) {
			n=read();
			ull ans=0; ll lim=sqrt(n);
			for (ll l=1,r; l<=lim; l=r+1) {
				ll val=n/l/l;
				r=sqrt(n/val);
				ans+=(sum[r]-sum[l-1])*qsum(n/(l*l));
			}
			printf("%llu\n", ans);
		}
		exit(0);
	}
}

signed main()
{
	freopen("kfc.in", "r", stdin);
	freopen("kfc.out", "w", stdout);

	mu[1]=1;
	for (int i=2; i<N; ++i) {
		if (!npri[i]) pri[++pcnt]=i, mu[i]=-1;
		for (int j=1; j<=pcnt&&1ll*i*pri[j]<N; ++j) {
			npri[i*pri[j]]=1;
			if (!(i%pri[j])) break;
			else mu[i*pri[j]]=-mu[i];
		}
	}
	// cout<<"mu: "; for (int i=1; i<N; ++i) printf("%d ", mu[i]);
	// force::solve();
	task::solve();

	return 0;
}
posted @ 2021-11-01 14:57  Administrator-09  阅读(0)  评论(0编辑  收藏  举报