标签:amp swap ret str inf eof return val 质因数
首先不考虑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] ); }
标签:amp swap ret str inf eof return val 质因数
原文地址:http://www.cnblogs.com/A-LEAF/p/7639549.html