BZOJ 3529 SDOI2014 數表 莫比烏斯反演+樹狀陣列
阿新 • • 發佈:2019-01-25
題目大意:令F(i)為i的約數和,多次詢問對於1<=x<=n,1<=y<=m,F(gcd(x,y))<=a的所有數對(x,y),求ΣF(gcd(x,y))%(2^31)
n,m<=10^5,a<=10^9
首先如果不考慮a的限制 令g(i)為1<=x<=n,1<=y<=m,gcd(x,y)=i的數的個數
那麼顯然有
利用線性篩處理出F(i) 那麼答案顯然是
治好了我多年的公式恐懼症。。。
現在我們只需要求出的字首和 這個問題就能在O(√n)的時間內出解
列舉每一個i 列舉i的倍數 暴力即可求出這個函式 然後處理字首和即可 複雜度是O(nlogn)的
那麼現在有了a的限制怎麼搞呢?
我們發現對答案有貢獻的i只有F(i)<=a的i 那麼我們將詢問按照a從小到大排序 將F(i)從小到大排序 每次詢問將<=a的F(i)按照之前的方式暴力插入 用樹狀陣列來維護這個字首和
這題就搞出來了
時間複雜度O(nlog^2n+q√nlogn) 有點卡。。。取模那裡自然溢位int就行了 最後再對2147483647取一下&即可
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 100100 using namespace std; struct query{ int n,m,a,_id; bool operator < (const query &x) const { return a < x.a ; } }queries[20200]; int T,ans[20200]; pair<int,int>f[M]; int mu[M],prime[M],tot; bool not_prime[M]; void Linear_Shaker() { static int min_factor_a[M],min_factor_sum[M]; /* 12=2*2*3 F(12)=(1+2+4)*(1+3) min_factor_a[12]=2*2=4 min_factor_sum[12]=1+2+4=7 */ int i,j; f[1]=make_pair(1,1);mu[1]=1; for(i=2;i<=100000;i++) { f[i].second=i; if(!not_prime[i]) { prime[++tot]=i; min_factor_a[i]=i; f[i].first=min_factor_sum[i]=i+1; mu[i]=-1; } for(j=1;j<=tot&&prime[j]*i<=100000;j++) { not_prime[prime[j]*i]=1; if(i%prime[j]==0) { f[prime[j]*i].first=f[i].first/min_factor_sum[i]* (min_factor_sum[prime[j]*i]=min_factor_sum[i]+min_factor_a[i]*prime[j]); min_factor_a[prime[j]*i]=min_factor_a[i]*prime[j]; mu[prime[j]*i]=0; break; } f[prime[j]*i].first=f[i].first*(prime[j]+1); min_factor_a[prime[j]*i]=prime[j]; min_factor_sum[prime[j]*i]=prime[j]+1; mu[prime[j]*i]=-mu[i]; } } } namespace BIT{ int c[M]; inline void Update(int x,int y) { for(;x<=100000;x+=x&-x) c[x]+=y; } inline int Get_Ans(int x) { int re=0; for(;x;x-=x&-x) re+=c[x]; return re; } } int Query(int n,int m) { int i,last,re=0; if(n>m) swap(n,m); for(i=1;i<=n;i=last+1) { last=min(n/(n/i),m/(m/i)); re+=(n/i)*(m/i)*(BIT::Get_Ans(last)-BIT::Get_Ans(i-1)); } return re&2147483647; } int main() { int i,j,k; Linear_Shaker(); sort(f+1,f+100000+1); cin>>T; for(i=1;i<=T;i++) scanf("%d%d%d",&queries[i].n,&queries[i].m,&queries[i].a),queries[i]._id=i; sort(queries+1,queries+T+1); for(i=1,j=1;i<=T;i++) { for(;j<=100000&&f[j].first<=queries[i].a;j++) for(k=f[j].second;k<=100000;k+=f[j].second) BIT::Update(k,f[j].first*mu[k/f[j].second]); ans[queries[i]._id]=Query(queries[i].n,queries[i].m); } for(i=1;i<=T;i++) printf("%d\n",ans[i]); return 0; }