description
求\[\prod_{i=1}^n\sigma_0(i)^{\mu(i)+i}(mod\ 10^{12}+39)\]其中\(\sigma_0(i)\)表示约数个数。
solution
菜鸡fdf现在才学\(Min\_25\)筛。
拆幂即转化为\((\prod_{i=1}^n\sigma_0(i)^{\mu(i)})(\prod_{i=1}^n\sigma_0(i)^i)\)。
Part 1
求\[\prod_{i=1}^n\sigma_0(i)^{\mu(i)}\]
唔[托腮]......考虑一下μ(i)≠0的条件,每个质因子只出现一次。--GuessYCB
因此\[\prod_{i=1}^n\sigma_0(i)^{\mu(i)}=2^{\sum_{i=1}^{n}\mu(i)c(i)}\]
即只须计算\(\sum_{i=1}^{n}\mu(i)c(i)\),其中\(c(i)\)表示\(i\)的质因子个数。
考虑怎么用\(Min\_25\)筛筛出这个东西。
首先我们可以很轻易的算出\(g(n,P)=\sum_{i=1}^{n}[i\in Prime]\mu(i)c(i)\)。
如果正常的算\(S(n,j)\),化简即\(S(n,j)=\sum_{i=j}^{P}f(p_i)S(\lfloor\frac{n}{p_i}\rfloor,i+1)-\sum_{i=1}^{j}f(p_i)\),那么我们少算了由于\(p_i\)这个新的质因子加入而产生的对\(c(n)\)的贡献。
因此我们再开一个\(S‘(n,j)\)表示\(\sum_{i=1}^{n}[p_{min}(i)\ge p_j]\mu(i)\),在\(S\)的转移式中处理一下,这样就可以做了。
Part 2
求\[\prod_{i=1}^n\sigma_0(i)^i\]考虑对\(\sigma_0(i)\)进行质因数分解,于是有\[\prod_{i=1}^{n}\sigma_0(i)^{i}=\prod_{p\in Prime}\prod_{k=1}(k+1)^{s(n,p,k)}\]
其中\(s(n,p,k)\)表示\(1-n\)中有多少个数可以表示成\(p^ka(gcd(p,a)=1)\)的形式。
可以知道\(s(n,p,k)=p^ks(\lfloor\frac{n}{p^k}\rfloor)-p^{k+1}s(\lfloor\frac{n}{p^{k+1}}\rfloor)\),其中\(s(n)=\sum_{i=1}^{n}i\)
质数的乘积考虑分块。
当\(p\le\sqrt n\)时,直接枚举\(p\)和\(k\)即可,因为这种形式的枚举和\(Min\_25\)筛相同,因此复杂度也同级。
当\(p>\sqrt n\)时,可以知道\(k=1\)。那么\(s(n,p,k)=p^ks(\lfloor\frac{n}{p^k}\rfloor)\)。数论分块+\(Min\_25\)即可。
至此问题得到解决。
#include<bits/stdc++.h>
#define FL "a"
using namespace std;
typedef long long ll;
typedef long double dd;
const int N=1e6+10;
const ll mod=1e12+39;
const ll phi=mod-1;
inline ll read(){
ll data=0,w=1;char ch=getchar();
while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘))ch=getchar();
if(ch==‘-‘)w=-1,ch=getchar();
while(ch<=‘9‘&&ch>=‘0‘)data=data*10+ch-48,ch=getchar();
return data*w;
}
inline void file(){
freopen(FL".in","r",stdin);
freopen(FL".out","w",stdout);
}
ll n;
inline void upd1(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
inline void dec1(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline void upd2(ll &a,ll b){a+=b;if(a>=phi)a-=phi;}
inline void dec2(ll &a,ll b){a-=b;if(a<0)a+=phi;}
inline ll mul1(ll a,ll b){ll r=(dd)a*b/mod;return a*b-r*mod;}
inline ll mul2(ll a,ll b){ll r=(dd)a*b/phi;return a*b-r*phi;}
inline ll poww(ll a,ll b){
ll res=1;
b=(b%phi+phi)%phi;
assert(b>=0);
for(;b;b>>=1,a=mul1(a,a))
if(b&1)res=mul1(res,a);
return res;
}
int cnt,pri[N];ll sump[N];bool vis[N];
inline void sieve(){
register int i,j;
for(vis[1]=1,i=2;i<N;i++){
if(!vis[i])pri[++cnt]=i,sump[cnt]=sump[cnt-1],upd2(sump[cnt],i);
for(j=1;j<=cnt&&1ll*i*pri[j]<N;j++){
vis[i*pri[j]]=1;if(i%pri[j]==0)break;
}
}
}
int sqr,tot,id1[N],id2[N];ll w[N],sum[N],sp[N],f[N],g[N];
#define ID(x) (x<=sqr?id1[x]:id2[n/(x)])
inline ll solve(ll n){
register ll ans,i,j,id,k,a,b,tmp;
for(sqr=sqrt(n),tot=0,i=1;i<=n;i=j+1){
j=n/(n/i);w[++tot]=n/i;
w[tot]<=sqr?id1[w[tot]]=tot:id2[n/w[tot]]=tot;
}
for(i=1;i<=tot;i++){
if(w[i]&1)sum[i]=mul2((w[i]+1)/2,w[i]);
else sum[i]=mul2(w[i]/2,w[i]+1);
sp[i]=sum[i];dec2(sp[i],1);
g[i]=w[i]-1;
}
for(i=1;i<=cnt&&1ll*pri[i]*pri[i]<=n;i++)
for(j=1;1ll*pri[i]*pri[i]<=w[j];j++){
id=ID(w[j]/pri[i]);
dec2(sp[j],mul2(pri[i],sp[id])),upd2(sp[j],mul2(pri[i],sump[i-1]));
dec2(g[j],g[id]);upd2(g[j],i-1);
}
for(i=1;i<=tot;i++)f[i]=0,dec2(f[i],g[i]),g[i]=f[i];
for(i=cnt;i;i--)
if(1ll*pri[i]*pri[i]<=n)
for(j=1;1ll*pri[i]*pri[i]<=w[j];j++){
id=ID(w[j]/pri[i]);
dec2(g[j],g[id]);dec2(g[j],i);
dec2(f[j],f[id]);dec2(f[j],g[id]);dec2(f[j],mul2(2,i));
}
ans=poww(2,f[1]);
for(i=1;i<=cnt&&1ll*pri[i]*pri[i]<=n;i++)
for(k=1,a=pri[i],b=1ll*pri[i]*pri[i];a<=n;k++,a=b,b*=pri[i]){
tmp=mul2(a,sum[ID(n/a)]);if(b<=n)dec2(tmp,mul2(b,sum[ID(n/b)]));
ans=mul1(ans,poww(k+1,tmp));
}
for(i=pri[i-1]+1,j=n/(n/i);i<j;i++)
if(!vis[i])ans=mul1(ans,poww(2,mul2(i,n/i)));
for(;i<=n;i=j+1){
j=n/(n/i);
tmp=sp[ID(j)];dec2(tmp,sp[ID(i-1)]);
tmp=mul2(tmp,sum[ID(n/i)]);
ans=mul1(ans,poww(2,tmp));
}
return ans;
}
int main()
{
int T=read();sieve();
while(T--){
n=read();
printf("%lld\n",solve(n));
}
return 0;
}
原文地址:https://www.cnblogs.com/cjfdf/p/10226424.html