1. 程式人生 > >bzoj_3529 數表

bzoj_3529 數表

min sof 條件 color 分解因數 sdoi 約數和 soft oid

首先不考慮a的限制

設 S(i)為i的約數和

據約數和定理

先將i分解因數

$$ i=p_1^{q_1}p_2^{q_2}...p_k^{q_k}$$

$$S(i)=\prod_{i=1}^k\sum_{j=0}^{q_i}p_i^j$$

當i與j互質時,S(i*j)=S(i)*S(j),滿足積性函數性質,所以可以線性刪出來

設g(i)為i最小質因數各冪次的加和

1.當i是質數,g(i)=S(i)=i+1

2.當i不與p(質數)互質是,S(i*p)=S(i)/g(i)*g(i*p)

3.當i與p互質時,S(i*p)=S(i)*(p+1)

(具體可見code)

題目讓求$$ans=\sum_{i=1 j=1}^{i<=n j<=m}S(gcd(i,j))$$

設f(i)為gcd(x,y)==i的(x,y)數

F(i)為i|gcd(x,y)的(x,y)數

$$ f(i)=\sum_{i|d}\mu(\frac{d}{i})F(d)$$

$$ f(i)=\sum_{i|d}\mu(\frac{d}{i})\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{i}\rfloor$$

那麽

$$ans=\sum_{i=1}^{min(n,m)}S(i)f(i)$$

$$(枚舉約數) ans=\sum_{i=1}^{min(n,m)}S(i)\sum_{i|d}\mu(\frac{d}{i})\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor$$

$$(枚舉d) ans=\sum_{d=1}^{min(n,m)}\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor\sum_{i|d}S(i)\mu(\frac{d}{i})$$

然後考慮加上a的限制條件,發現只要離線處理,用樹狀數組維護後面一項就行了

技術分享
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#define
ll long long #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int M=20006; const int N=100006; struct VV { int v,order; bool friend operator < (VV a,VV b) { return a.v<b.v; } }ji[N]; int prime[N],cnt; bool he[N]; int mu[N],g[N]; void chu() { mu[1]=1;g[1]=1;ji[1].v=1;ji[1].order=1; for(int i=2;i<N;++i) { ji[i].order=i; if(!he[i]) { prime[++cnt]=i; mu[i]=-1; g[i]=i+1; ji[i].v=i+1; } for(int j=1;j<=cnt&&prime[j]*i<N;++j) { he[i*prime[j]]=1; if(i%prime[j]==0) { mu[i*prime[j]]=0; g[i*prime[j]]=g[i]*prime[j]+1; ji[i*prime[j]].v=ji[i].v/g[i]*g[i*prime[j]]; break; } mu[i*prime[j]]=-mu[i]; g[i*prime[j]]=prime[j]+1; ji[i*prime[j]].v=ji[i].v*(prime[j]+1); } } /*printf("\n"); for(int i=1;i<=10;++i) printf("%d ",ji[i].v); printf("\n");*/ sort(ji+1,ji+N); } struct Q { int n,m,A; int order; bool friend operator < (Q a,Q b) { return a.A<b.A; } }q[M]; int an[M]; int m; int c[N]; void add(int pos,int val) { for(int i=pos;i<N;i+=(i&(-i)) ) c[i]+=val; } int qq(int pos) { int ans=0; for(int i=pos;i>0;i-=(i&(-i)) ) ans+=c[i]; return ans; } inline void mk(int pos,int val) { for(int i=pos;i<N;i+=pos ) { add(i,val*mu[i/pos]); }//cout<<1; } int get(int n,int m) { if(n>m) swap(n,m); int nx; int ans=0; for(int i=1;i<=n;) { nx=min( n/(n/i),m/(m/i) ); ans+=(n/i)*(m/i)*( qq(nx)-qq(i-1) ); i=nx+1; } return ans; } void work() { int IINF=(1<<31)-1,now=1; for(int i=1;i<=m;++i) { while(ji[now].v<=q[i].A) mk(ji[now].order,ji[now].v),++now; an[q[i].order]=get(q[i].n,q[i].m)&IINF; } } int main(){ //freopen("in.in","r",stdin); freopen("sdoi2014shb.in","r",stdin); freopen("sdoi2014shb.out","w",stdout); //freopen("out.out","w",stdout); chu(); scanf("%d",&m); for(int i=1;i<=m;++i) { q[i].order=i; scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].A); } sort(q+1,q+1+m); work(); for(int i=1;i<=m;++i) printf("%d\n",an[i] ); }
bzoj_3529

bzoj_3529 數表