题解 P6156 【简单题】
安利一下博客:题解 P6156 【简单题】
updated in 2020.8.31 :新增一种
简单题(确信)
不难发现:
把这个代进原式,然后开始推式子:
令
都是套路。
令
如果我们能求得
先考虑如何求
令
证明:
考虑枚举
- 若
x \leq n+1 ,则有x-1 个数对(i,j)(1 \leq i,j \leq n) 能表示出x ,则此时x 对S(n) 的贡献是x-1 。 - 若
n+1 <x \leq 2n ,设x=n+i \ (2 \leq i \leq n) 则有n-i+1 个数对(i,j)(1 \leq i,j \leq n) 能表示出x ,则此时x 对S(n) 的贡献是n-i+1 。
则有:
我们再把要证明的式子展开:
所以
然后发现这东西能用数学归纳法证明,上面这东西太暴力了。
当
假设
证毕。
线性筛出
这东西就是几个积性函数卷起来,所以
对于质数
对于
- 若
k=2 ,有f(p^2)=\mu(p^2)+p\mu^2(p)\mu(p)+p^2\mu^2(p^2)=-p 。 - 若
k>2 ,对于任意d ,都有d 或\frac{n}{d} 有平方因子,所以f(p^k)=0 。
然后就可以线性筛筛
inline void sieve()
{
f[1]=1;
for(int i=2;i<maxn;++i)
{
if(!flag[i]) prime[++cnt]=i,f[i]=i-1;
for(int j=1;j<=cnt&&i*prime[j]<maxn;++j)
{
flag[i*prime[j]]=true;
if(i%prime[j]) f[i*prime[j]]=f[i]*f[prime[j]]%mod;// 积性函数
else
{
if((i/prime[j])%prime[j])// 互质则用积性函数的性质
f[i*prime[j]]=(mod-prime[j])*f[i/prime[j]]%mod;
// 不互质则说明prime[j]的次数大于2
break;
}
}
}
}
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define maxn 10000005
#define Rint register int
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const lxl mod=998244353;
template <typename T>
inline T read()
{
T x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
inline lxl fmi(lxl a,lxl b)
{
lxl ans=1;
a%=mod;
while(b>0)
{
if(b&1) ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
int n;
lxl k;
int prime[maxn],cnt;
bool flag[maxn];
lxl f[maxn],F[maxn];
inline void sieve()
{
f[1]=F[1]=1;
for(int i=2;i<maxn;++i)
{
if(!flag[i]) prime[++cnt]=i,f[i]=i-1,F[i]=fmi(i,k);
for(int j=1;j<=cnt&&i*prime[j]<maxn;++j)
{
flag[i*prime[j]]=true;
F[i*prime[j]]=F[i]*F[prime[j]]%mod;
if(i%prime[j]) f[i*prime[j]]=f[i]*f[prime[j]]%mod;
else
{
if((i/prime[j])%prime[j])
f[i*prime[j]]=(mod-prime[j])*f[i/prime[j]]%mod;
break;
}
}
}
for(int i=1;i<maxn;++i) f[i]=(f[i-1]+f[i]*F[i]%mod)%mod,F[i]=(F[i]+F[i-1])%mod;
for(int i=1;i<maxn;++i) F[i]=(F[i]+F[i-1])%mod;
}
inline lxl S(int n)
{
return (F[n<<1]-2*F[n]%mod+mod)%mod;
}
inline lxl calcu(lxl n)
{
lxl res=0;
for(lxl l=1,r=0;l<=n;l=r+1)
{
r=n/(n/l);
res=(res+S(n/l)*(f[r]-f[l-1]+mod)%mod)%mod;
}
return res;
}
int main()
{
// freopen("P6156.in","r",stdin);
n=read<int >(),k=read<lxl >();
sieve();
printf("%lld\n",calcu(n));
return 0;
}