P6156 简单题(推式子&莫反&整除分块)

P6156 简单题(推式子&莫反&整除分块)_整除

https://www.luogu.com.cn/problem/solution/P6156

P6156 简单题(推式子&莫反&整除分块)_ios_02

P6156 简单题(推式子&莫反&整除分块)_i++_03
P6156 简单题(推式子&莫反&整除分块)_ios_04


// Problem: P6156 简单题
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P6156
// Memory Limit: 250 MB
// Time Limit: 1000 ms
// Date: 2021-07-07 21:28:20
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e7+10,M=2e4+5,inf=0x3f3f3f3f,mod=998244353;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
int p[N],cnt;
bitset<N>vis;
ll f[N],F[N];
ll ksm(ll a,ll n,ll m=mod){
	ll ans=1;
	while(n){
		if(n&1) ans=ans*a%m;
		a=a*a%m;
		n>>=1;
	}
	return ans;
}
ll n,k;
void init(int n){
	vis[1]=F[1]=f[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]) p[++cnt]=i,f[i]=i-1,F[i]=ksm(i,k,mod);
		for(ll j=1;j<=cnt&&i*p[j]<=n;j++){
			vis[i*p[j]]=1;
			F[i*p[j]]=F[i]*F[p[j]]%mod;
			if(i%p[j]==0){
				int x=i/p[j];
				if(x%p[j]) f[i*p[j]]=(mod-p[j])*f[x]%mod;
				break; 
			}
			f[i*p[j]]=f[i]*f[p[j]]%mod;
		}
	}
	for(int i=1;i<=n;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<=n;i++) F[i]=(F[i]+F[i-1])%mod;
}
ll fun(ll n){
	return ((F[n<<1]-(F[n]<<1))%mod+mod)%mod;
}

ll solve(ll n){
	ll s=0;
	for(ll l=1,r;l<=n;l=r+1){
		r=n/(n/l); 
		s+=fun(n/l)*(f[r]-f[l-1]+mod)%mod;
		s%=mod;
	}
	return s;
}
int main(){
	scanf("%lld%lld",&n,&k);
	k%=(mod-1);
	init(N-1);
	printf("%lld\n",solve(n));
	return 0;
}