zoukankan      html  css  js  c++  java
  • [51nod1965]奇怪的式子

    description

    求$$prod_{i=1}nsigma_0(i){mu(i)+i}(mod 10^{12}+39)$$其中(sigma_0(i))表示约数个数。

    solution

    菜鸡fdf现在才学(Min\_25)筛。

    拆幂即转化为((prod_{i=1}^nsigma_0(i)^{mu(i)})(prod_{i=1}^nsigma_0(i)^i))

    Part 1

    求$$prod_{i=1}nsigma_0(i){mu(i)}$$

    唔[托腮]......考虑一下μ(i)≠0的条件,每个质因子只出现一次。--GuessYCB
    

    因此$$prod_{i=1}nsigma_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}[iin Prime]mu(i)c(i))
    如果正常的算(S(n,j)),化简即(S(n,j)=sum_{i=j}^{P}f(p_i)S(lfloorfrac{n}{p_i} floor,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}nsigma_0(i)i$$考虑对(sigma_0(i))进行质因数分解,于是有$$prod_{i=1}{n}sigma_0(i){i}=prod_{pin 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(lfloorfrac{n}{p^k} floor)-p^{k+1}s(lfloorfrac{n}{p^{k+1}} floor)),其中(s(n)=sum_{i=1}^{n}i)
    质数的乘积考虑分块。
    (plesqrt n)时,直接枚举(p)(k)即可,因为这种形式的枚举和(Min\_25)筛相同,因此复杂度也同级。
    (p>sqrt n)时,可以知道(k=1)。那么(s(n,p,k)=p^ks(lfloorfrac{n}{p^k} floor))。数论分块+(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
    ",solve(n));
      }
      return 0;
    }
    
    
  • 相关阅读:
    用指针写线段树(维护乘法)
    费用流——网络流板子
    最小割板子题——[USACO5.4]奶牛的电信
    数论——置换
    NOIP2012 借教室
    POJ1990 moofest
    POJ2352 star
    POJ2299 Ultra-QuickSort
    CF498D Traffic Jams in the land
    POJ2828 Buy Ticket
  • 原文地址:https://www.cnblogs.com/cjfdf/p/10226424.html
Copyright © 2011-2022 走看看