洛咕3312 [SDOI2014]數表
阿新 • • 發佈:2018-12-08
洛咕3312 [SDOI2014]數表
終於獨立寫出一道題了。。。真tm開心(還是先寫完題解在寫的)
先無視a的限制,設\(f[i]\)表示i的約數之和
不妨設\(n<m\)
\(Ans=\sum_{i=1}^n\sum_{j=1}^mf[\gcd(i,j)]\)
\(Ans=\sum_{x=1}^nf[x]\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=x]\)
莫比烏斯反演,\(Ans=\sum_{x=1}^nf[x]\sum_{x|y}\mu(\frac{y}{x})\lfloor\frac{n}{y}\rfloor\lfloor\frac{m}{y}\rfloor\)
換個方法列舉,列舉\(\frac{y}{x}\)
\(Ans=\sum_{x=1}^nf[x]\sum_{y=1}^{n/x}\mu(y)\lfloor\frac{n}{xy}\rfloor\lfloor\frac{m}{xy}\rfloor\)
先列舉\(xy\),再列舉\(x\)
\(Ans=\sum_{x=1}^n\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{x}\rfloor\sum_{y|x}^nf[y]\mu(\frac{x}{y})\)
前面數論分塊,後面預處理
現在有了a的限制,只要將詢問按照a排序,樹狀陣列維護字首和,每次加入即可
#include<bits/stdc++.h> #define il inline #define vd void typedef long long ll; il int gi(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')f=-1; ch=getchar(); } while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } struct naive{unsigned int f,i;}s[100010]; il bool operator<(const naive&a,const naive&b){return a.f<b.f;} struct ques{int n,m,a,i;}Q[100010]; il bool operator<(const ques&a,const ques&b){return a.a<b.a;} unsigned int pri[100010],pr,mu[100010],f[100010],ans[100010]; bool yes[100010]; unsigned int t[100010]; il vd update(int x,unsigned int p){while(x<100001)t[x]+=p,x+=x&-x;} il unsigned int query(int x){unsigned int ret=0;while(x)ret+=t[x],x-=x&-x;return ret;} int main(){ mu[1]=1; for(int i=2;i<100001;++i){ if(!yes[i])pri[++pr]=i,mu[i]=-1; for(int j=1;j<=pr&&i*pri[j]<100001;++j){ yes[i*pri[j]]=1; if(i%pri[j]==0){mu[i*pri[j]]=0;break;} mu[i*pri[j]]=-mu[i]; } } for(int i=1;i<100001;++i) for(int j=i;j<100001;j+=i) f[j]+=i; for(unsigned int i=1;i<100001;++i)s[i]=(naive){f[i],i}; std::sort(s+1,s+100001); int q=gi(),n,m,a; for(int i=1;i<=q;++i)n=gi(),m=gi(),a=gi(),Q[i]=(ques){n,m,a,i}; std::sort(Q+1,Q+q+1); int p=1; for(int i=1;i<=q;++i){ while(p<100001&&s[p].f<=Q[i].a){ for(int j=s[p].i;j<100001;j+=s[p].i)update(j,mu[j/s[p].i]*f[s[p].i]); ++p; } n=Q[i].n,m=Q[i].m;if(n>m)std::swap(n,m); for(int l=1,r;l<=n;++l){ r=std::min(n/(n/l),m/(m/l)); ans[Q[i].i]+=(query(r)-query(l-1))*(n/l)*(m/l); l=r; } } for(int i=1;i<=q;++i)printf("%u\n",ans[i]&2147483647); return 0; }