Description
σ(i) σ ( i ) 表示i的约数个数
Solution
本题要用Min_25筛,
本题要用LL*LL取模,恶心…
考虑把答案拆成两半计算:
∏ni=1σ0(i)i∗∏ni=1σ0(i)μ(i)
∏
i
=
1
n
σ
0
(
i
)
i
∗
∏
i
=
1
n
σ
0
(
i
)
μ
(
i
)
先考虑前半部分怎么处理:
显然的结论:设
x=∏pcjj
x
=
∏
p
j
c
j
,p为互不相同的质数
σ0(i)=∏(cj+1)
σ
0
(
i
)
=
∏
(
c
j
+
1
)
那我们答案就是:(设
Sum(x)=(x+1)x/2
S
u
m
(
x
)
=
(
x
+
1
)
x
/
2
)
对于小于 n−−√ n 的质数直接计算,对于大于的 n−−√ n 质数,k只能等于1,
暴力的做法:直接设 S(n,j)=∑ni=2[i为质数或i的最小质因子大于pj]∗Sum(⌊ni⌋) S ( n , j ) = ∑ i = 2 n [ i 为 质 数 或 i 的 最 小 质 因 子 大 于 p j ] ∗ S u m ( ⌊ n i ⌋ )
正确做法:
S(n,j)=∑ni=2[i为质数或i的最小质因子大于pj]∗i
S
(
n
,
j
)
=
∑
i
=
2
n
[
i
为
质
数
或
i
的
最
小
质
因
子
大
于
p
j
]
∗
i
也就是直接筛质数,做后计算答案的时候再分块一下即可
对于后面的部分,显然的,每个质数最多出现一次,这个直接设
F(n,j)=∑ni=2[i为质数或i的最小质因子大于pj]∗μ(i)∗(i的质因子个数)
F
(
n
,
j
)
=
∑
i
=
2
n
[
i
为
质
数
或
i
的
最
小
质
因
子
大
于
p
j
]
∗
μ
(
i
)
∗
(
i
的
质
因
子
个
数
)
还要设一个
F1(n,j)=∑ni=2[i为质数或i的最小质因子大于pj]∗μ(i)
F
1
(
n
,
j
)
=
∑
i
=
2
n
[
i
为
质
数
或
i
的
最
小
质
因
子
大
于
p
j
]
∗
μ
(
i
)
来辅助转移,
复杂度: O(n34) O ( n 3 4 )
Code
#include <cstdio>
#include <algorithm>
#include <cmath>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
typedef long long LL;
const int N=706000;
const LL mo=1e12+39;
const LL mo1=1e12+38;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int M;
LL n,ans;
int pr[N];
LL prs[N],prf[N];
bool prz[N];
LL chen(LL q,LL w,LL mo11=mo)
{
q%=mo11;w%=mo11;
LL tmp=(LL)((long double)q*w/mo11+1e-8)*mo11;
return (q*w-tmp+mo11)%mo11;
}
LL SUM(LL n,LL mo1=mo)
{
if(n<1e9)
{
return (n&1)?(((n+1)>>1)*n%mo1):((n>>1)*(n+1LL)%mo1);
}
return (n&1)?chen(((n+1)>>1),n,mo1):chen((n>>1),(n+1LL),mo1);
}
void Pre(int n)
{
fo(i,2,n)
{
if(!prz[i])pr[++pr[0]]=i,prs[pr[0]]=(prs[pr[0]-1]+pr[pr[0]])%mo1;
fo(j,1,pr[0])
{
int t=i*pr[j];
if(t>n)break;
prz[t]=1;
if(i%pr[j]==0)break;
}
}
}
LL ksm(LL q,LL w)
{
LL ans=1;
w=(w%mo1+mo1)%mo1;
for(;w;w>>=1,q=chen(q,q))
if(w&1)ans=chen(ans,q);
return ans;
}
LL f[N];
LL d[N];
int id[N],id1[N];
LL g[N],g1[N];
void GS(LL n)
{
d[0]=0;
for(LL i=1,nx;i<=n;i=nx+1)
{
nx=n/(n/i);
LL t=n/i;
d[++d[0]]=t;
f[d[0]]=SUM(t,mo1)-1;
g[d[0]]=t-1;
if(t<=M)id[t]=d[0];
else id1[n/t]=d[0];
}
fo(j,1,pr[0])
{
LL li=(LL)pr[j]*pr[j];
for(int i=1;d[i]>=li;++i)
{
LL t1=d[i]/pr[j];
int t=(t1>M)?id1[n/t1]:id[t1];
f[i]=(f[i]-(f[t]-prs[j-1])*(LL)pr[j])%mo1;
g[i]=(g[i]-(g[t]-j+1))%mo1;
}
}
fo(i,1,d[0])if(d[i]>pr[pr[0]])f[i]=(f[i]-prs[pr[0]])%mo1;else f[i]=0;
LL t=0;
fo(i,1,d[0])if(d[i]>pr[pr[0]])t=(t+chen((f[i]-f[i+1]),SUM(n/d[i],mo1),mo1))%mo1;
ans=chen(ans,ksm(2,t));
fo(i,1,d[0])g1[i]=g[i]=mo1-g[i];
fod(j,pr[0],1)
{
LL li=(LL)pr[j]*pr[j];
for(int i=1;d[i]>=li;++i)
{
LL t1=d[i]/pr[j];
int t=(t1>M)?id1[n/t1]:id[t1];
g[i]=(g[i]-(g[t]+j)-(g1[t]+j))%mo1;
g1[i]=(g1[i]-(g1[t]+j))%mo1;
}
}
g[1]=(g[1]+mo1)%mo1;
ans=chen(ans,ksm(2,g[1]));
}
void Doit()
{
ans=1;
fo(i,1,pr[0])prf[i]=pr[i];
fo(i,1,64)
{
LL t=0;
fo(j,1,pr[0])
{
if(n<prf[j])break;
t=(t+(SUM(n/prf[j],mo1)-pr[j]*SUM(n/(prf[j]*pr[j]),mo1))%mo1*prf[j])%mo1;
prf[j]*=pr[j];
}
ans=chen(ans,ksm(i+1,t));
}
GS(n);
printf("%lld\n",ans);
}
int main()
{
int _;
M=500000;
Pre(M);
scanf("%d",&_);
while(_--)
{
scanf("%lld",&n);
Doit();
}
return 0;
}