莫比乌斯反演套路二--(n/d)(m/d)给提出来--BZOJ3529: [Sdoi2014]数表
一个数表上第i行第j列表示能同时整除i和j的自然数,Q<=2e4个询问,每次问表上1<=x<=n,1<=y<=m区域内所有<=a的数之和。n,m<=1e5,a<=1e9。对2^31取模。
这个a很讨厌就先不理他。首先i行j列的那个数其实是$a_{ij}=\sum_{x|gcd(i,j)} x$,令$s(t)=\sum_{x|t}x$,然后gcd(i,j)是只有1e5的,可以先把s数组预处理出来。s是积性函数所以线性筛可以搞,但复杂度不在这里,直接埃筛也行。
那现在就是看[1,min(n,m)]中每个数作为gcd的s(t)被算了多少次,也就是1<=x<=n,1<=y<=m中有多少(x,y)=t,记这次数叫f(t),那f(t)是经典的可以反演的式子,反演就不写了,最后$f(t)=\sum_{t|d}\mu(\frac{d}{t})\frac{n}{d}\frac{m}{d}$,最后要求的就是$\sum_{t=1}^{min(n,m)}s(t)\sum_{t|d}\mu(\frac{d}{t})\frac{n}{d}\frac{m}{d}$。
然后我就卡住了。这里用个套路二把后面那俩提出来,变成:$\sum_{d=1}^{min(n,m)}\frac{n}{d}\frac{m}{d}\sum_{t|d}s(t)\mu(\frac{d}{t})$,漂亮,后面那东西(记h(d))预处理一下即可,然后就\sqrt n出解。
然而有了a的限制之后,后面那东西就变得飘忽不定了,这时候需要离线,然后所有s(t)排个序,每次询问前把<=当前a的所有s(t)加给对应的h(d),然后查区间和用树状数组即可。这样就可以在$nlog^2 n+q\sqrt n logn$出解了。
然而排序时忘了cmp函数了。 然而过程中忘了取模导致爆longlong了。 然而没考虑到有负数。 然而树状数组忘开longlong了。
然而最后跑得贼慢,其实对2^31取模只需要int自然溢出最后&2147483647即可。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 //#include<bitset> 6 #include<algorithm> 7 //#include<cmath> 8 using namespace std; 9 10 int T,n,m,A; 11 #define maxn 100011 12 int miu[maxn],s[maxn],prime[maxn],lp,us[maxn]; bool notprime[maxn]; 13 int snum[maxn]; 14 bool cmp(const int &a,const int &b) {return s[a]<s[b];} 15 void pre(int n) 16 { 17 for (int i=1;i<=n;i++) 18 for (int j=i;j<=n;j+=i) 19 s[j]+=i; 20 for (int i=1;i<=n;i++) snum[i]=i; 21 sort(snum+1,snum+1+n,cmp); 22 miu[1]=1; lp=0; 23 for (int i=2;i<=n;i++) 24 { 25 if (!notprime[i]) {prime[++lp]=i; miu[i]=-1;} 26 for (int j=1;j<=lp && 1ll*prime[j]*i<=n;j++) 27 { 28 notprime[i*prime[j]]=1; 29 if (i%prime[j]) miu[i*prime[j]]=-miu[i]; 30 else {miu[i*prime[j]]=0; break;} 31 } 32 } 33 for (int i=1;i<=n;i++) 34 for (int j=i,cnt=1;j<=n;j+=i,cnt++) 35 us[j]+=miu[cnt]*s[i]; 36 } 37 38 39 #define LL long long 40 struct BIT 41 { 42 LL a[maxn],n; 43 BIT() {n=100001;} 44 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;} 45 LL query(int x) {LL ans=0; for (;x;x-=x&-x) ans+=a[x]; return ans;} 46 }t; 47 48 struct Q 49 { 50 int n,m,a,id; 51 bool operator < (const Q &b) const {return a<b.a;} 52 }q[maxn]; 53 LL ans[maxn]; 54 55 const int base=100001; 56 int main() 57 { 58 pre(base); 59 scanf("%d",&T); 60 for (int i=1;i<=T;i++) scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].a),q[i].id=i; 61 sort(q+1,q+1+T); 62 63 int j=1; 64 const LL tmp=1ll<<31; 65 for (int c=1;c<=T;c++) 66 { 67 while (j<=base && s[snum[j]]<=q[c].a) 68 { 69 for (int k=snum[j],cnt=1;k<=base;k+=snum[j],cnt++) 70 t.add(k,s[snum[j]]*miu[cnt]); 71 j++; 72 } 73 LL Ans=0; 74 for (int i=1,to=min(q[c].n,q[c].m),last;i<=to;i=last+1) 75 { 76 last=min(q[c].n/(q[c].n/i),q[c].m/(q[c].m/i)); 77 Ans+=1ll*(q[c].n/i)*(q[c].m/i)*(t.query(last)-t.query(i-1))%tmp, 78 Ans-=Ans>=tmp?tmp:0,Ans+=Ans<0?tmp:0; 79 } 80 ans[q[c].id]=Ans; 81 } 82 83 for (int c=1;c<=T;c++) printf("%lld\n",ans[c]); 84 return 0; 85 }