P3312-[SDOI2014]数表【莫比乌斯反演,树状数组】
正題
題目鏈接:https://www.luogu.com.cn/problem/P3312
題目大意
定義F(x)F(x)F(x)表示xxx的約數和
給出n,m,an,m,an,m,a,求∑i=1n∑j=1m[F(gcd(i,j))≤a]?F(gcd(i,j))\sum_{i=1}^n\sum_{j=1}^m[F(gcd(i,j))\leq a]*F(gcd(i,j))i=1∑n?j=1∑m?[F(gcd(i,j))≤a]?F(gcd(i,j))
解題思路
首先我們不考慮aaa的限制,我們定義g(i)=∑i∣dμ(id)?ni??mi?g(i)=\sum_{i|d}\mu(\frac{i}ozvdkddzhkzd)\lfloor \frac{n}{i}\rfloor\lfloor \frac{m}{i}\rfloorg(i)=∑i∣d?μ(di?)?in???im??。那么我們有ans=∑i=1nF(i)g(i)=∑i=1nF(i)∑i∣dμ(id)?ni??mi?ans=\sum_{i=1}^nF(i)g(i)=\sum_{i=1}^nF(i)\sum_{i|d}\mu(\frac{i}ozvdkddzhkzd)\lfloor \frac{n}{i}\rfloor\lfloor \frac{m}{i}\rfloorans=i=1∑n?F(i)g(i)=i=1∑n?F(i)i∣d∑?μ(di?)?in???im??
?ans=∑d=1n?ni??mi?∑i∣dF(i)μ(di)\Rightarrow ans=\sum_{d=1}^n\lfloor \frac{n}{i}\rfloor\lfloor \frac{m}{i}\rfloor\sum_{i|d}F(i)\mu(\fracozvdkddzhkzd{i})?ans=d=1∑n??in???im??i∣d∑?F(i)μ(id?)
顯然我們可以計算∑i∣dF(i)μ(di)\sum_{i|d}F(i)\mu(\fracozvdkddzhkzd{i})∑i∣d?F(i)μ(id?)的前綴和來統計
考慮aaa的限制,我們發現對于F(i)>aF(i)>aF(i)>a那么有F(i)=0F(i)=0F(i)=0。我們可以將詢問的aaa從小到大排序,然后按照F(i)μ(di)F(i)\mu(\fracozvdkddzhkzd{i})F(i)μ(id?)從小到大的順序插入,因為要求前綴和,所以在樹狀數組里插入即可。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #define lowbit(x) (x&-x) using namespace std; const int N=1e5+10; int T,n[N],m[N],a[N],p[N],t[N],nm; int mu[N],f[N],g[N],pri[N],q[N],ans[N]; bool vis[N]; void prime(){int cnt=0;mu[1]=f[1]=1;for(int i=2;i<=nm;i++){if(!vis[i])vis[i]=1,pri[++cnt]=i,f[i]=g[i]=i+1,mu[i]=-1;for(int j=1;j<=cnt&&pri[j]*i<=nm;j++){vis[pri[j]*i]=1;if(i%pri[j]==0){mu[i*pri[j]]=0;g[i*pri[j]]=g[i]*pri[j]+1;f[i*pri[j]]=f[i]/g[i]*g[i*pri[j]];break;}mu[i*pri[j]]=-mu[i];f[i*pri[j]]=f[i]*f[pri[j]];g[i*pri[j]]=pri[j]+1;}}for(int i=1;i<=nm;i++)q[i]=i; } void Change(int x,int val){while(x<=nm){t[x]+=val;x+=lowbit(x);}return; } int Ask(int x){int ans=0;while(x){ans+=t[x];x-=lowbit(x);}return ans; } bool cmp(int x,int y) {return a[x]<a[y];} bool cMp(int x,int y) {return f[x]<f[y];} int main() {scanf("%d",&T);for(int i=1;i<=T;i++){scanf("%d%d%d",&n[i],&m[i],&a[i]);p[i]=i;}nm=100000;prime();sort(p+1,p+1+T,cmp);sort(q+1,q+1+nm,cMp);int jz=1;for(int i=1;i<=T;i++){int x=p[i];while(jz<=nm&&f[q[jz]]<=a[x]){for(int j=q[jz];j<=nm;j+=q[jz])Change(j,f[q[jz]]*mu[j/q[jz]]);jz++;}if(n[x]>m[x])swap(n[x],m[x]);for(int l=1,r;l<=n[x];l=r+1){r=min(n[x]/(n[x]/l),m[x]/(m[x]/l));ans[x]+=(n[x]/l)*(m[x]/l)*(Ask(r)-Ask(l-1));}}for(int i=1;i<=T;i++)printf("%d\n",ans[i]&(~(1<<31))); }總結
以上是生活随笔為你收集整理的P3312-[SDOI2014]数表【莫比乌斯反演,树状数组】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P2257-YY的GCD【莫比乌斯反演】
- 下一篇: P3327-[SDOI2015]约数个数