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;
}
静渊以有谋,疏通而知事。