HDU 6588 Function 2019 杭电多校第一场 HDU 1011 Function

Function

本题大佬们都是用线性过的,蒟蒻用nlogn苟过去

题意

\sum_{i=1}^{n} gcd(i,\sqrt[3]{i}})

分析

显然\sqrt[3]{i}可以分块,1=\sqrt[3]{1}-\sqrt[3]{7},2=\sqrt[3]{8}-\sqrt[3]{26},3=\sqrt[3]{27}-\sqrt[3]{63},\cdots,n=\sqrt[3]{n^3}-\sqrt[3]{(n+1)^3-1}

易知,原式为

\sum_{i=1}^{1\leqslant n\leqslant 7}gcd(1,i)+\sum_{i=8}^{8\leqslant n\leqslant 26}gcd(2,i)+\sum_{i=27}^{27\leqslant n\leqslant 63}gcd(3,i)+\cdots+\sum_{i=n^3}^{n^3 \leqslant n\leqslant (n+1)^3-1}gcd(n,i)

又因为gcd(n,m)=gcd(n,n+m),所以易知gcd可以以n为周期转移

\sum_{i=1}^{n}gcd(i,n)=\sum_{i=n+1}^{2*n}gcd(i,n)

所以我们可以以n为模块转移

(i+1)^3-i^3=2*i^2+3*i

\sum_{i=n^3}^{n^3 \leqslant n\leqslant (n+1)^3-1}gcd(n,i)=(2*i+3)*\sum_{i=1}^{n}gcd(i,n)+gcd(n,n^3)

\sum_{i=1}^{n} gcd(i,\sqrt[3]{i}}) = \sum_{i=1}^{n}\sum_{j=n^3}^{n^3 \leqslant n\leqslant (n+1)^3-1}gcd(i,j)=\sum_{i=1}^{n}{(2*i+3)*\sum_{j=1}^{i}gcd(j,i)+i}

\sum_{i=1}^{n}gcd(i,n)求法

枚举GCD

统计gcd(i,N)=x的个数,发现其个数为\Theta(\frac{N}{x})

因为x为N的因数,gcd(i,N)=x,i应与\frac{N}{x}互质

f(x)=\sum x*\Theta(\frac{N}{x})

 

LL SumGcd(int n,BL k) {
	LL Ans=(k/n)*ans[n]%mod;
	k=k%n;
	if(!k)return Ans;
	LL r;
	for(int l=1; l*l<=n; l++) {
		r=n/(n/l);
		if(n%l==0) {
			Ans=(Ans+phi[l]*(k/l))%mod;
			if(l*l<n)Ans=(Ans+phi[n/l]*(k/(n/l)))%mod;
		}
		l=r;
	}
	return Ans;
}

欧拉函数是非完全积性函数,积性函数的约数和也是积性函数

f(N)=f(p_{1}^{a_{1}})*f(p_{2}^{a_{2}})*\cdots *f(p_{n}^{a_{n}})

f(p^n)=\Theta(p^n)+p*\Theta(p^{n-1})+p^2*\Theta(p^{n-2})+\cdots+p^n*\Theta(1)

若a为质数,b mod a=0,phi[a*b]=phi[b]*a

f(p^n)=(p-1)*p^{n-1}+p*(p-1)*p^{n-2}+\cdots+p^n

f(p^n)=n*(p-1)*p^{n-1}+p^n

以下代码对1-maxn对分解质因数,对1-maxn求\sum_{i=1}^{n}gcd(i,n)

void GetSum() {
	for (int i = 1; i <= maxn; i++)ans[i] = 1, num[i] = i;
	int g, m, n, p;
	for (int i = 0; prime[i]*prime[i]<=maxn; i++) {
		p = prime[i];
		for (int j = p; j <= maxn; j += p) {
			g = 0;
			m = n = num[j];
			while (n % p == 0) {
				n /= p;
				g++;
			}
			ans[j] = ans[j] * (m / n / p * g * (p - 1) + m / n) % mod;
			num[j] = n;
		}
	}
	for (int i = 1; i <= maxn; i++)
		if (num[i] > 1)
			ans[i] = ans[i] * (2 * num[i] - 1) % mod;
	LL s = 3;
	for (int i = 1; i <= maxn; i++) {
		s += 3;
		sum[i] =(sum[i-1]+i+ s * ans[i] % mod)%mod;
	}
}

代码

#include <iostream>
#include <cstdio>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long  LL;
typedef __int128 BL;
const int maxn = 10000005;
const LL mod = 998244353;
bool vis[maxn + 5];
int prime[maxn + 5], cnt,phi[maxn];
void Phi() {
	phi[1] = 1;
	vis[1] = true;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
		for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			phi[i * prime[j]] = phi[i] * (prime[j] - 1);
		}
	}
}
int num[maxn + 5];
LL ans[maxn + 5], sum[maxn + 5];
void GetSum() {
	for (int i = 1; i <= maxn; i++)ans[i] = 1, num[i] = i;
	int g, m, n, p;
	for (int i = 0; prime[i]*prime[i]<=maxn; i++) {
		p = prime[i];
		for (int j = p; j <= maxn; j += p) {
			g = 0;
			m = n = num[j];
			while (n % p == 0) {
				n /= p;
				g++;
			}
			ans[j] = ans[j] * (m / n / p * g * (p - 1) + m / n) % mod;
			num[j] = n;
		}
	}
	for (int i = 1; i <= maxn; i++)
		if (num[i] > 1)
			ans[i] = ans[i] * (2 * num[i] - 1) % mod;
	LL s = 3;
	for (int i = 1; i <= maxn; i++) {
		s += 3;
		sum[i] =(sum[i-1]+i+ s * ans[i] % mod)%mod;
	}
}
BL read() {
	BL ret = 0, f = 1;
	char ch = getchar();
	while (ch<'0' || ch > '9') {
		if (ch == '-')
			f = -f;
		ch = getchar();
	}
	while (ch >= '0'&&ch <= '9') {
		ret = ret * 10 + ch - '0';
		ch = getchar();
	}
	return ret *= f;
}
LL SumGcd(int n,BL k) {
	LL Ans=(k/n)*ans[n]%mod;
	k=k%n;
	if(!k)return Ans;
	LL r;
	for(int l=1; l*l<=n; l++) {
		r=n/(n/l);
		if(n%l==0) {
			Ans=(Ans+phi[l]*(k/l))%mod;
			if(l*l<n)Ans=(Ans+phi[n/l]*(k/(n/l)))%mod;
		}
		l=r;
	}
	return Ans;
}
LL res[30];
int main() {
	Phi();
	GetSum();
	int t;
	scanf("%d",&t);
	while(t--) {
		BL n=read();
		int l=1,r=maxn,mid,p;
		while(l<=r) {
			mid=(l+r)/2;
			if(n>BL(mid)*mid*mid-1) {
				p=mid;
				l=mid+1;
			} else r=mid-1;
		}
		LL Ans=sum[p-1];
		LL k=n-BL(p)*p*p+1;
		if(k==0) {
			printf("%lld\n",Ans);
		} else {
			k--;
			Ans+=p;
			if(k==0) {
				printf("%lld\n",Ans);
			} else {
				LL res=(Ans+SumGcd(p,k%p)+(k/p)*ans[p])%mod;
				printf("%lld\n",res);
			}
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值