test20181101 怜香惜玉 和 BZOJ2226 LCMSum

怜香惜玉

分析

观察(直到考试最后一小时我才尝试打表)发现若\(\gcd(x,i)=1\),则\(\gcd(x,x-i)=1\),所以是对称的。

那么又由于乘了2,所以\(f(x)=x\)

然后打个快速幂,求个前缀和就行了。

时间复杂度\(O(n \log n)\)

co int MAXN=1e6+1,mod=998244353;

int qpow(int x,int k)
{
	int res=1;
	while(k)
	{
		if(k&1)
			res=(ll)res*x%mod;
		x=(ll)x*x%mod,k>>=1;
	}
	return res;
}

int ans[MAXN];

int main()
{
	int T,k;
	read(T);read(k);
	for(int i=1;i<MAXN;++i)
	{
		ans[i]=qpow(i,k);
		(ans[i]+=ans[i-1])%=mod;
	}
	while(T--)
	{
		printf("%d\n",ans[read<int>()]);
	}
    return 0;
}

拓展

L巨:这题是套路,经常用到。

然而由于L巨太巨了,所以L巨还是帮我把这个式子用莫比乌斯反演证明出来了。

要证明的是

\[\sum_{i=0}^{n}i \cdot [\gcd(i,n)=1] = \frac{(\varphi(n) + e(n)) \cdot n}{2} \]

加上一个e是因为按题意phi(1)=2

证明

\[左边 \\ =\sum_{i=0}^{n} i \cdot \sum_{d|i且d|n} \mu(d) \\ =\sum_{d|n} \mu(d) \sum_{i=0}^{\lfloor \frac{n}{d} \rfloor} d \cdot i \\ =\sum_{d|n} \mu(d) \cdot d \cdot \frac{\frac{n}{d}(\frac{n}{d}+1)}{2} \\ =\frac{n}{2}(\mu*id+e)(n) \\ =\frac{n \cdot (\varphi(n) + e(n))}{2} \\ =右边 \]

解释

第三步d整除n,所以去掉了下取整符号,转化为等差数列求和。

倒数第二步在消掉分子分母中同时出现的数。

倒数第一步,由于有

\[\mu * 1 = e \\ \varphi * 1 = id \]

所以交叉卷积,消去1得到

\[\mu * id = \varphi \]

LCMSum

给定\(n(n \leq 10^6)\),求

\[\sum_{i=1}^{n} \textrm{lcm}(i,n) \]

\(T(T \leq 3 \times 10^5)\)组询问。

分析

https://blog.sengxian.com/solutions/bzoj-2226?tdsourcetag=s_pcqq_aiomsg

\[\sum_{i=1}^{n}\textrm{lcm}(i,n) \\ =\sum_{i=1}^{n}\frac{i \cdot n}{\gcd(i,n)}\\ =n \sum_{d|n}\frac{1}{d}\sum_{i=1}^{n}[\gcd(i,n)=d] \cdot i\\ =n \sum_{d|n}\frac{1}{d}\sum_{i=1}^{\frac{n}{d}}[\gcd(i,\frac{n}{d})=1] \cdot i \cdot d \\ = n \sum_{d|n} \sum_{i=1}^{\frac{n}{d}} [\gcd(i,\frac{n}{d})=1] \cdot i \]

后半部分参照上一题,可得

\[原式 =n \sum_{d|n} \frac{(\varphi(n) + e(n)) \cdot n}{2} \\ =\frac{n}{2} \sum_{d|n} (\varphi(n) + e(n)) \cdot n \]

现在的这个后面的式子\(O(n)\)线性筛后,枚举倍数\(O(n \ln n)\)预处理。

然后就能\(O(1)\)回答每次询问。

时间复杂度\(O(n + n \ln n + T)\)

co int MAXN=1e6+7;
int prime[MAXN],pcnt;
int phi[MAXN];
ll f[MAXN];

void linear()
{
	prime[1]=1;
	phi[1]=1;
	for(int i=2;i<MAXN;++i)
	{
		if(!prime[i])
		{
			prime[++pcnt]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=pcnt&&i*prime[j]<MAXN;++j)
		{
			prime[i*prime[j]]=1;
			phi[i*prime[j]]=phi[i]*phi[prime[j]];
			if(i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
		}
	}
	for(int i=1;i<MAXN;++i)
		for(int j=i;j<MAXN;j+=i)
			f[j]+=(ll)phi[i]*i;
}

ll solve(int n)
{
	return (f[n]+1)*n/2;
}

int main()
{
	linear();
	int T=read<int>();
	while(T--)
	{
		printf("%lld\n",solve(read<int>()));
	}
    return 0;
}

posted on 2018-11-01 21:26  autoint  阅读(188)  评论(0编辑  收藏  举报

导航