首页 > 其他 > 详细

51nod1222 最小公倍数计数

时间:2018-03-03 10:25:47      阅读:269      评论:0      收藏:0      [点我收藏+]

求$\sum_{i=1}^{n}\sum_{j=1}^{n}[[i,j\leq n]$。n<1e11。

方法零:变不等为相等,直接反演,求其前缀和

$\sum_{i=1}^{n}\sum_{j=1}^{n}[[i,j]=n]$

闪一句:反演!!!

$=\sum_{d|n}\mu(d)\sum_{i=1}^n\sum_{j=1}^i[[i,j]|\frac{n}{d}]$

闪一句:$\sum_{i=1}^n\sum_{j=1}^i[[i,j]|\frac{n}{d}]=\sum_{i=1}^{n}\sum_{j=1}^{i}[i|\frac{n}{d}\wedge j|\frac{n}{d}]=\frac{(d(\frac{n}{d})+1)(d(\frac{n}{d}))}{2}$

$=\sum_{d|n}\mu(d)\frac{(d(\frac{n}{d})+1)(d(\frac{n}{d}))}{2}$

$=\frac{1}{2}(\sum_{d|n}\mu(d)d^2(\frac{n}{d})+\sum_{d|n}\mu(d)d(\frac{n}{d}))$

分别求括号里两坨东西的前缀和。

$\sum_{i=1}^{n}\sum_{d|i}\mu(d)d(\frac{i}{d})$

$=\sum_{d=1}^n\mu(d)\sum_{k=1}^{\left \lfloor \frac{n}{d} \right \rfloor}d(k)$

$=\sum_{d=1}^n\mu(d)\sum_{k=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\left \lfloor \frac{n}{kd} \right \rfloor$

$\sum_{i=1}^{n}\sum_{d|i}\mu(d)d^2(\frac{i}{d})$

$=\sum_{d=1}^{n}\mu(d)\sum_{k=1}^{\left \lfloor \frac{n}{d} \right \rfloor}d^2(k)$

$\mu$的前缀和用杜教筛。整除函数的前缀和可用类似杜教筛的方法。约数个数的平方的前缀和可用洲阁筛,似乎最后可$\sqrt{n}$时间对每个$\frac{n}{i}$的取值的对应前缀和求出,我不太会就用了$n^{\frac{2}{3}}$的方法。

结果?妥妥的卡空间,空间开小卡时间。

技术分享图片

技术分享图片
  1 //#include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 //#include<map>
  6 #include<math.h>
  7 //#include<time.h>
  8 //#include<complex>
  9 #include<algorithm>
 10 using namespace std;
 11 
 12 #define LL long long
 13 LL n,a,b;
 14 
 15 LL md=3000000,mz=320000;  
 16 #define maxa 3000011
 17 short miu[maxa],summiu[maxa],d[maxa],ci[maxa];unsigned int sumd2[maxa];int mi[maxa],sumd[maxa],prime[maxa/10],lp,lw; bool notprime[maxa];
 18 #define maxb 640011
 19 LL g[maxb],ff[maxb],who[maxb],i0[maxb],sp[maxb];
 20 void pre()
 21 {
 22     miu[1]=summiu[1]=sumd[1]=sumd2[1]=d[1]=1; lp=0;
 23     for (int i=2;i<=md;i++)
 24     {
 25         if (!notprime[i]) {prime[++lp]=i; miu[i]=-1; d[i]=2; mi[i]=i; ci[i]=1;}
 26         summiu[i]=summiu[i-1]+miu[i];
 27         sumd[i]=sumd[i-1]+d[i];
 28         sumd2[i]=sumd2[i-1]+d[i]*d[i];
 29         for (int j=1,tmp;j<=lp && 1ll*i*prime[j]<=md;j++)
 30         {
 31             notprime[tmp=i*prime[j]]=1;
 32             if (i%prime[j]) {miu[tmp]=-miu[i]; d[tmp]=d[i]*2; mi[tmp]=prime[j]; ci[tmp]=1;}
 33             else {miu[tmp]=0; d[tmp]=d[i/mi[i]]*(ci[i]+2); mi[tmp]=mi[i]*prime[j]; ci[tmp]=ci[i]+1; break;}
 34         }
 35     }
 36     int tmp=0;
 37     for (int i=2;i<=mz;i++) {sp[i]=sp[i-1]+!notprime[i]; if (!notprime[i]) tmp++;}
 38     lp=tmp-1; mz=prime[tmp]-1;
 39 }
 40 
 41 #define maxh 1000007
 42 struct Hash
 43 {
 44     int first[maxh],le; struct Edge{LL to,v; int next;}edge[maxb];
 45     void clear(LL n) {le=2; for (LL i=1;i<=n;i=n/(n/i)+1) first[n/i%maxh]=0;}
 46     void insert(LL x,LL y) {int z=x%maxh; Edge &e=edge[le]; e.to=x; e.v=y; e.next=first[z]; first[z]=le++;}
 47     LL find(LL x) {int z=x%maxh; for (int i=first[z];i;i=edge[i].next) if (edge[i].to==x) return edge[i].v; return -1;}
 48 }hm,hz;
 49 
 50 LL dumiu(LL n)
 51 {
 52     if (n<=md) return summiu[n];
 53     LL tmp=hm.find(n); if (tmp!=-1) return tmp;
 54     LL ans=1;
 55     for (LL i=2,last;i<=n;i=last+1)
 56     {
 57         last=n/(n/i);
 58         ans-=dumiu(n/i)*(last-i+1);
 59     }
 60     hm.insert(n,ans); return ans;
 61 }
 62 
 63 LL dud(LL n)
 64 {
 65     if (n<=md) return sumd[n];
 66     LL ans=0;
 67     for (LL i=1,last;i<=n;i=last+1)
 68     {
 69         last=n/(n/i);
 70         ans+=(last-i+1)*(n/i);
 71     }
 72     return ans;
 73 }
 74 
 75 void mg(LL n)
 76 {
 77     lw=0; hz.clear(n); for (LL i=1;i<=n;i=n/(n/i)+1) lw++,who[lw]=g[lw]=n/i,hz.insert(who[lw],lw);
 78     memset(i0,0,sizeof(i0));
 79     for (int i=1;i<=lp;i++)
 80         for (int j=1;j<=lw && (LL)prime[i]*prime[i]<=who[j];j++)
 81         {
 82             int k=hz.find(who[j]/prime[i]);
 83             g[j]-=g[k]-(i-1-i0[k]);
 84             i0[j]=i;
 85         }
 86 }
 87 
 88 void mff(LL n)
 89 {
 90     for (int i=lp;i;i--)
 91         for (int j=1;j<=lw && (LL)prime[i]*prime[i]<=who[j];j++)
 92         {
 93             if (prime[i+1]>who[j]) ff[j]=1;
 94             else if ((LL)prime[i+1]*prime[i+1]>who[j]) ff[j]=(sp[min(mz,who[j])]-sp[prime[i+1]-1])*4+1;
 95             LL tmp=prime[i],k2;
 96             for (int c=1;tmp<=who[j];tmp*=prime[i],c++)
 97             {
 98                 LL now=who[j]/tmp;
 99                 if (prime[i+1]>now) k2=1;
100                 else if (prime[i+1]*(LL)prime[i+1]>now) k2=(sp[min(mz,now)]-sp[prime[i+1]-1])*4+1;
101                 else k2=ff[hz.find(now)];
102                 ff[j]+=k2*(c+1)*(c+1);
103             }
104         }
105 }
106 
107 LL list[maxb];
108 void zh(LL n)
109 {
110     for (int i=1;i<=lw;i++)
111     {
112         if ((LL)4>who[i]) list[i]=1;
113         else list[i]=ff[i];
114         if (who[i]>md) for (int j=1,last;j<=mz;j=last+1)
115         {
116             LL tmp=who[i]/j; last=min(mz,who[i]/tmp);
117             if (prime[lp+1]>tmp) continue;
118             int id=hz.find(tmp);
119             list[i]+=(sumd2[last]-sumd2[j-1])*(g[id]-1-(lp-i0[id]))*4;
120         }
121         else list[i]=sumd2[who[i]];
122     }
123 }
124 
125 LL calc(LL n)
126 {
127     mg(n); mff(n); zh(n);
128     LL ans=0;
129     hm.clear(n);
130     for (LL i=1,last;i<=n;i=last+1)
131     {
132         last=n/(n/i);
133         ans+=(dumiu(last)-dumiu(i-1))*dud(n/i);
134     }
135     for (LL i=1,last;i<=n;i=last+1)
136     {
137         last=n/(n/i);
138         ans+=(dumiu(last)-dumiu(i-1))*list[hz.find(n/i)];
139     }
140     return ans>>1;
141 }
142 
143 int main()
144 {
145     scanf("%lld%lld",&a,&b);
146     pre();
147     LL ans=-calc(a-1); ans+=calc(b);
148     printf("%lld\n",ans);
149     return 0;
150 }
View Code

 

51nod1222 最小公倍数计数

原文:https://www.cnblogs.com/Blue233333/p/8495737.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!