51nod 1965 奇怪的式子——min_25筛

题目:http://www.51nod.com/Challenge/Problem.html#!#problemId=1965

考虑  \( \prod_{i=1}^{n}\sigma_0^i \)

    \(=\prod_{j=1}^{p_j<=n}\prod_{t=1}^{p_j^t<=n}(t+1)^{ p_j^tS(\left\lfloor\frac{n}{p_j^t}\right\rfloor) - p_j^{t+1}S(\left\lfloor\frac{n}{p_j^{t+1}}\right\rfloor) } \)

  (其中 \( S(x)=\frac{(1+x)*x}{2} \))

对于 \( <=\sqrt(n) \) 的质数暴力枚举;对于 \( >\sqrt(n) \) 的质数只能是 1 次方,所以就是要求

    \( \sum\limits_{\sqrt(n)<p_j<=n}S(\left\lfloor\frac{n}{p_j}\right\rfloor)*p_j \)

\( S(\left\lfloor\frac{n}{p_j}\right\rfloor) \) 可以分块,所以就是要求区间内的质数个数(\( <= \sqrt(n) \) 的暴枚减掉就行);min_25 筛做一下就行。

考虑  \( \prod_{i=1}^{n}\sigma_0^{\mu(i)} \)

    \(=2^{\sum\limits_{i=1}^{n}d(i)*\mu(i)} \) ,其中 \( d(i) \) 表示 i 的质因子个数。

令 \( g(n,j)=\sum\limits_{i=1}^{n}[min_i>=p_j]\mu(i) \) , \( s(n,j)=\sum\limits_{i=1}^{n}[min_i>=p_j]d(i)*\mu(i) \)

则 \( g(n,j)=g(n,j+1)+(-1)g(\frac{n}{p_j},j+1)+(-1) \) , \( s(n,j)=s(n,j+1)+(-1)s(\frac{n}{p_j},j+1)+(-1)g(\frac{n}{p_j},j+1)+(-1) \)

对于\( min_i>\sqrt(n) \) 的部分的贡献,可以通过赋初值来处理。筛一个 \( c2 \) 表示质数个数就行。

需要注意的是在调用 \( g(\frac{n}{p_j},j+1) \) 和 \( s(\frac{n}{p_j},j+1) \) 的时候,因为 \( \frac{n}{p_j} \) 比 n 小,又有从大到小枚举 \( p_j \) 并且 \( if(p^{2}_{j}>w[i])break; \) ,所以可能 \( \frac{n}{p_j} \) 没被更新过,还是初值;这时它的值是 \( >\sqrt{\frac{n}{p_j}} \) 的质数贡献,但现在要用的是 \( 1~\sqrt{\frac{n}{p_j}} \) 里 \( min_i > p_j \) 的数的贡献;不过这种情况中有贡献的只有质数,所以像赋初值那样算一下应该贡献的值就行了。

可以用大数乘法的黑科技,就是 \( a*b%mod = a*b - \left\lfloor\frac{a*b}{mod}\right\rfloor * mod \) ,超过的部分 long long 自然溢出即可;那个除的结果需要正确,所以转成 long double 计算再赋值给 long long 即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define ld long double
using namespace std;
const ll mod=1e12+39,md=mod-1;/////
ll upt(ll x){while(x>=md)x-=md;while(x<0)x+=md;return x;}
ll Ml(ll a,ll b,ll Md=md){ll ret=(ld)a*b/Md;return a*b-ret*Md;}
ll pw(ll x,ll k)//mod!! not md
{ll ret=1;while(k){if(k&1)ret=Ml(ret,x,mod);x=Ml(x,x,mod);k>>=1;}return ret;}
const int N=640000;
int base,m,cnt; bool vis[N];
ll n,w[N],c[N],c2[N],s[N],g[N],p[N],p2[N],sp[N],sm[N];
//c:sm of P, c2:ct of P, s:u*d, g:u, p2:p^2, sp:sm of P(base), sm:(1+x)*x/2
ll cal(ll x){if(x&1ll)return Ml((1+x)/2,x); else return Ml(1+x,x/2);}
void init()
{
  base=sqrt(n);m=cnt=0;
  memset(vis,0,sizeof vis);
  sm[m+1]=c[m+1]=0;/////
  for(int i=2;i<=base;i++)
    {
      if(!vis[i])
    {p[++cnt]=i;p2[cnt]=(ll)i*i;sp[cnt]=upt(sp[cnt-1]+i);}
      for(int j=1,d;j<=cnt&&(d=i*p[j])<=base;j++)
    {vis[d]=1; if(i%p[j]==0)break;}
    }
  for(ll i=1,j;i<=n;i=n/j+1)w[++m]=j=n/i;
  for(int i=1;i<=m;i++)sm[i]=cal(w[i]);
}
int Id(ll x){if(!x)return 0;return x<=base?m-x+1:n/x;}
void cz()
{
  for(int i=1;i<=m;i++)c[i]=upt(sm[i]-1),c2[i]=w[i]-1;
  for(int j=1;j<=cnt;j++)
    for(int i=1;i<=m&&p2[j]<=w[i];i++)
      {
    int k=Id(w[i]/p[j]);
    c[i]=upt(c[i]-Ml(p[j],upt(c[k]-sp[j-1])));
    c2[i]=upt(c2[i]-(c2[k]-(j-1)));
      }

  int p0=cnt;
  for(int i=1;i<=m;i++)
    {
      while(p0&&p2[p0]>w[i])p0--;
      g[i]=s[i]=upt(p0-c2[i]);//>sqrt(n)
    }
  int i,lst=0;
  for(int j=cnt;j;j--)
    {
      for(i=1;i<=m&&p2[j]<=w[i];i++)
    {
      int k=Id(w[i]/p[j]);ll d1=g[k],d2=s[k];
      if(k>lst)d1=upt(j-c2[k]),d2=d1;//can't use ini but only P contribt
      g[i]=upt(g[i]-d1-1);//-1 for p[j]
      s[i]=upt(s[i]-d2-d1-1);
    }//g[] lack of mu[1]
      lst=i-1;
    }
}
const int Lg=38;//lg=37 t+1=38
ll cs[Lg+5];
int main()
{
  int T;scanf("%d",&T);
  while(T--)
    {
      scanf("%lld",&n);init();cz();
      ll ans=1;memset(cs,0,sizeof cs);
      for(int j=1;j<=cnt;j++)
    {
      ll m1=p[j],m2=m1*m1;//m1<=base so m2<=n for now
      for(int t=1;m1<=n;t++,m1=m2,m2*=p[j])//n*sqrt(n) is ok
        cs[t+1]=upt(cs[t+1]+Ml(m1,sm[Id(n/m1)])-Ml(m2,sm[Id(n/m2)]));
    }//sm[Id(n/m2)] may = sm[Id(0)] = sm[m+1]
      for(int i=3;i<=Lg;i++)ans=Ml(ans,pw(i,cs[i]),mod);

      ll ret=0;//cs of 2
      for(ll i=1,j,d;i<=n;i=j+1)
    {
      j=n/i;d=sm[Id(j)];j=n/j;
      ret=upt(ret+Ml(d,upt(c[Id(j)]-c[Id(i-1)])));/////c[Id(0)]=c[m+1]
    }
      for(int j=1;j<=cnt;j++)ret=upt(ret-Ml(p[j],sm[Id(n/p[j])]));
      ret=upt(ret+s[1]+cs[2]);
      ans=Ml(ans,pw(2,ret),mod);
      printf("%lld\n",ans);
    }
  return 0;
}

 

posted on 2019-01-18 14:47  Narh  阅读(194)  评论(0编辑  收藏  举报

导航