jsk41390(min25筛)

题目链接

https://nanti.jisuanke.com/t/41390

题解

可以发现 $f(ab)=f(a)+f(b)$ ,那么

对 $k\ge2$ ,$p\le\sqrt n$ 可以直接暴力

对 $k=1$ ,我们只需要求区间上的素数个数和素数和,但是注意到区间是分块整除形成的区间,所以可以直接利用预处理的函数




代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
*         ┏┓    ┏┓
*         ┏┛┗━━━━━━━┛┗━━━┓
*         ┃       ┃  
*         ┃   ━    ┃
*         ┃ >   < ┃
*         ┃       ┃
*         ┃... ⌒ ...  ┃
*         ┃ ┃
*         ┗━┓ ┏━┛
*          ┃ ┃ Code is far away from bug with the animal protecting          
*          ┃ ┃ 神兽保佑,代码无bug
*          ┃ ┃           
*          ┃ ┃       
*          ┃ ┃
*          ┃ ┃           
*          ┃ ┗━━━┓
*          ┃ ┣┓
*          ┃ ┏┛
*          ┗┓┓┏━━━━━━━━┳┓┏┛
*           ┃┫┫ ┃┫┫
*           ┗┻┛ ┗┻┛
*/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<set>
#include<bitset>
#include<complex>
#include<assert.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1ll<<x)
#define mid (x+y>>1)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define NM 200005
#define nm 2000005
using namespace std;
const double pi=acos(-1);
const ll inf=998244353;
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}



inline void reduce(ll&x){x+=x>>63&inf;}
inline ll qpow(ll x,ll t){
ll s=1;
for(;t;t>>=1,x=x*x%inf)if(t&1)s=s*x%inf;
return s;
}
ll n;
ll w[NM],f[NM],g[NM],pre[NM];
int tot,m;
ll prime[NM];
bool v[NM];
ll ans;
inline int id(ll x){if(x)return x<=m/2?m-x+1:n/x;else return 0;}


void init(){
m=sqrt(n);
inc(i,2,m)if(!v[i]){
prime[++tot]=i;
for(int j=i<<1;j<=m;j+=i)v[j]++;
}
inc(i,1,tot)pre[i]=(pre[i-1]+prime[i])%inf;
inc(i,1,m)w[i]=n/i;
while(w[m]>1)w[m+1]=w[m]-1,m++;
}





int main(){
n=read();
init();
inc(i,1,m)f[i]=w[i]%inf-1,g[i]=w[i]%inf*((w[i]+1)%inf)%inf*(inf+1>>1)%inf-1;
inc(j,1,tot){
inc(i,1,m)if(w[i]>=prime[j]*prime[j]){
int k=id(w[i]/prime[j]);
reduce(f[i]-=f[k]-j+1);
reduce(g[i]-=prime[j]*(g[k]-pre[j-1]+inf)%inf);
}else break;
}
for(ll x=1,y,t;x<=n;x=y+1){
y=n/(n/x);t=n/x%inf;
reduce(ans+=(n+1)%inf*t%inf*(f[id(y)]-f[id(x-1)]+inf)%inf-inf);
reduce(ans-=t*(t+1)%inf*(inf+1>>1)%inf*(g[id(y)]-g[id(x-1)]+inf)%inf);
}
//printf("%lld\n",ans);
inc(k,2,34){
for(int j=1;j<=tot;j++){
ll _t=1;
inc(i,1,k){
_t*=prime[j];
if(_t>n)break;
}
if(_t>n)break;
ll t=n/_t%inf;
_t%=inf;
reduce(ans+=(n+1)*t%inf-inf);
reduce(ans-=_t*t%inf*(t+1)%inf*(inf+1>>1)%inf);
}
}
printf("%lld\n",ans);
return 0;
}