您的位置:首页 > 其它

bzoj 3529: [Sdoi2014]数表

2017-08-10 11:44 274 查看


orz:popoqqq

此题比较强(起码我这个蒟蒻觉得)

主要是那个<=a的限制很烦。

经过测试,暴力求约数和函数是非常快的,于是可以离线+树状数组暴力维护前缀和做。

code:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int mu[100010],prime[100010],pr=0,tr[100010];
int ans[100010];
bool v[100010];
struct node{int x,num;}f[100010];
struct list{int n,m,a,num;}q[20010];
void pre()
{
memset(v,true,sizeof(v));
mu[1]=1;
for(int i=2;i<=100000;i++)
{
if(v[i]) prime[++pr]=i,mu[i]=-1;
for(int j=1;j<=pr&&i*prime[j]<=100000;j++)
{
v[i*prime[j]]=false;
if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=100000;i++)
for(int j=i;j<=100000;j+=i)
f[j].x+=i;
for(int i=1;i<=100000;i++) f[i].num=i;
}
int lowbit(int x){return x&(-x);}
void change(int k,int c)
{
for(int i=k;i<=100000;i+=lowbit(i))
tr[i]+=c;
}
int get(int k)
{
int ans=0;
for(int i=k;i>=1;i-=lowbit(i))
ans+=tr[i];
return ans;
}
bool cmp(node a,node b){return a.x<b.x;}
bool cmp1(list a,list b){return a.a<b.a;}
int main()
{
pre();
int T;scanf("%d",&T);
for(int i=1;i<=T;i++) scanf("%d %d %d",&q[i].n,&q[i].m,&q[i].a),q[i].num=i;
sort(f,f+100001,cmp);
sort(q,q+T+1,cmp1);
memset(tr,0,sizeof(tr));
int now=0;
for(int k=1;k<=T;k++)
{
while(now+1<=100000&&f[now+1].x<=q[k].a)
{
now++;int i=f[now].num;
for(int j=i;j<=100000;j+=i)
change(j,f[now].x*mu[j/i]);
}
int pos,n=q[k].n,m=q[k].m;
if(n>m) swap(n,m);
for(int i=1;i<=n;i=pos+1)
{
pos=min(n/(n/i),m/(m/i));
ans[q[k].num]+=(n/i)*(m/i)*(get(pos)-get(i-1));
}
}
for(int i=1;i<=T;i++)
printf("%d\n",ans[i]&0x7fffffff);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: