南昌邀请赛网络赛 G. tsy's number(莫比乌斯反演+线性筛)

题目链接:

tsy's number

 

题意:

求  \sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{k=1}^{n}\frac{\phi(i)\phi(j^{2})\phi(k^{3})}{\phi(i)\phi(j)\phi (k)}\phi (gcd(i,j,k))  (mod 2^{30}

 

思路:

原式 = \sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{k=1}^{n}j*k^{2}*\phi (gcd(i,j,k))=\sum_{d=1}^{n}\phi (d)\sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{k=1}^{n}j*k^{2}[gcd(i,j,k)=d]

=\sum_{d=1}^{n}\phi (d)*d^{3}\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\sum_{k=1}^{n/d}j*k^{2}[gcd(i,j,k)=1]

设  f(x)=\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\sum_{k=1}^{n/d}j*k^{2}[gcd(i,j,k)=x]

设 g(x)=\sum_{x|d}^{ }f(d)=\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\sum_{k=1}^{n/d}j*k^{2}[x|gcd(i,j,k)]

=\sum_{i=1}^{n/xd}\sum_{j=1}^{n/xd}\sum_{k=1}^{n/xd}j*k^{2}[1|gcd(i,j,k)]*x^{3}=x^{3}\sum_{i=1}^{n/xd}1\sum_{j=1}^{n/xd}j\sum_{k=1}^{n/xd}k^{2}

=x^{3}*\left \lfloor \frac{n}{xd} \right \rfloor*\frac{(1+\left \lfloor \frac{n}{xd} \right \rfloor)*\left \lfloor \frac{n}{xd} \right \rfloor}{2}*\frac{(1+\left \lfloor \frac{n}{xd} \right \rfloor)*\left \lfloor \frac{n}{xd} \right \rfloor*(2*\left \lfloor \frac{n}{xd} \right \rfloor+1)}{6}

f(x)=\sum_{x|d}^{ }\mu(\frac{d}{x})*g(d)

f(1)=\sum_{1|d}^{ }\mu(\frac{d}{x})*g(d)=\sum_{i=1}^{n/d}\mu(d)*g(d)

原式 = \sum_{d=1}^{n}\phi (d)*d^{3}\sum_{i=1}^{n/d}\mu (i)*i^{3}*\left \lfloor \frac{n}{id} \right \rfloor*\frac{(1+\left \lfloor \frac{n}{id} \right \rfloor)*\left \lfloor \frac{n}{id} \right \rfloor}{2}*\frac{(1+\left \lfloor \frac{n}{id} \right \rfloor)*\left \lfloor \frac{n}{id} \right \rfloor*(2*\left \lfloor \frac{n}{id} \right \rfloor+1)}{6}

设T = id ,将 i 的求和变为 T 的求和:

原式 = \sum_{T=1}^{n}\left \lfloor \frac{n}{T} \right \rfloor*\frac{(1+\left \lfloor \frac{n}{T} \right \rfloor)*\left \lfloor \frac{n}{T} \right \rfloor}{2}*\frac{(1+\left \lfloor \frac{n}{T} \right \rfloor)*\left \lfloor \frac{n}{T} \right \rfloor*(2*\left \lfloor \frac{n}{T} \right \rfloor+1)}{6} *\sum_{d|T}^{ }(\frac{T}{d})^{3}\mu (d)*d^{3}*\phi (\frac{T}{d})

\sum_{d|T}^{ }(\frac{T}{d})^{3}\mu (d)*d^{3}*\phi (\frac{T}{d}):这个是g(x)=\mu (x)*x^{3} 与 f(x)=\phi (x)*x^{3} 的迪利克雷卷积,并且g(x)与f(x)均为积性函数,因此该函数也为积性函数,可通过线性筛O(n)求解。

处理上述积性函数前缀和,对原式前半部分的 \left \lfloor \frac{n}{T} \right \rfloor 进行数论分块即可,单次询问复杂度 O(sqrt(n)) 。

线性筛:

1. i = p,p为质数时,sum[i]=p^{3}(p-1)-p^{3}

2. i 为合数:

    i%prime[j] != 0:sum[i*prime[j]]=sum[i]*prime[j]^{3}*(prime[j]-1)-sum[i]*prime[j]^{3}

    i%prime[j] == 0:分两种情况:

    <1> i 中只有一个prime[j]的因子:

          sum[i*p]=sum[i/p]*p^{3}*(p-1)*p*p^{3}-sum[i/p]*p^{3}*(p-1)*p^{3}  

    <2> i 中存在 prime[j]^{k} 的因子,k>=2

          sum[i*p]=sum[i]*p*p^{3}

 i%prime[j] == 0要分两种情况是因为\sum_{d|T}^{ }\phi (\frac{T*p}{d}) 中,(T/d)可能%p == 0,可能 != 0 。

若 i % p ==0 ,\phi (i*p) = p * \phi (i) 

若 i % p !=0 ,\phi (i*p) = (p-1)*\phi (i) 

 

Tips:2^{30} 与2和6不互质,除以2,除以6的时候不能算逆元。

 

Code:

#include 
using namespace std;

typedef long long ll;

const int MAX = 1e7 + 10;
const ll inf = 1e18;
const ll mod = 1ll << 30;

ll m, n, p;
ll prime[MAX + 10], sum[MAX + 10];
int vis[MAX + 10];

void init()
{
	memset(vis, 0, sizeof(vis));
	sum[1] = 1;
	int tot = 0;
	for (int i = 2; i <= MAX; i++) {
		if (!vis[i]) {
			prime[++tot] = i;
			sum[i] = 1ll * i * i%mod*i%mod*(i - 2) % mod;
		}
		for (int j = 1; j <= tot && i*prime[j] <= MAX; j++) {
			vis[i*prime[j]] = 1;
			if (i%prime[j] == 0) {
				if ((i / prime[j]) % prime[j] != 0) {
					ll tmp1 = sum[i / prime[j]] * prime[j] % mod*prime[j] % mod*prime[j] % mod*(prime[j] - 1) % mod*prime[j] % mod*prime[j] % mod*prime[j] % mod*prime[j] % mod;
					ll tmp2 = sum[i / prime[j]] * prime[j] % mod*prime[j] % mod*prime[j] % mod*(prime[j] - 1) % mod*prime[j] % mod*prime[j] % mod*prime[j] % mod;
					sum[i*prime[j]] = (tmp1 - tmp2 + mod) % mod;
				}
				else {
					sum[i*prime[j]] = sum[i] * prime[j] % mod*prime[j] % mod*prime[j] % mod*prime[j] % mod;
				}
				break;
			}
			else {
				sum[i*prime[j]] = sum[i] * sum[prime[j]] % mod;
			}
		}
	}
	for (int i = 1; i <= MAX; i++) {
		sum[i] = (sum[i] + sum[i - 1]) % mod;
	}
}

int main()
{
	int T;
	scanf("%d", &T);
	init();
	while (T--)
	{
		ll n;
		scanf("%lld", &n);
		ll ans = 0;
		ll pos = 0;
		for (int i = 1; i <= n; i = pos + 1) {
			pos = n / (n / i);
			ll w = n / i;
			ll tmp1 = (1 + w) *w / 2 % mod;
			ll tmp2 = w * (w + 1) / 2;
			if (tmp2 % 3 == 0)	tmp2 = tmp2 / 3 % mod*(2 * w + 1) % mod;
			else tmp2 = tmp2 % mod*((2 * w + 1) / 3 % mod) % mod;
			ll tmp = w * tmp1%mod*tmp2%mod;
			ans = (ans + (sum[pos] - sum[i - 1] + mod) % mod*tmp%mod) % mod;
		}
		printf("%lld\n", ans);
	}
	return 0;
}

 

你可能感兴趣的:(ACM-数论)