您的位置:首页 > 其它

【bzoj 3529】【sdoi 2014】数表

2017-08-13 07:38 357 查看

Description

有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为
能同时整除i和j的所有自然数之和。给定a,计算数表中不大于a的数之和。

Input

输入包含多组数据。
输入的第一行一个整数Q表示测试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描述一组数据。

Output

对每组数据,输出一行一个整数,表示答案模2^31的值。

Sample Input

2

4 4 3

10 10 5

Sample Output

20

148

HINT

1 < =N.m < =10^5 , 1 < =Q < =2×10^4

题解:

   %%%popoqqq。设:

   

,所以:

   


   先不考虑a的影响,设:


。所以

   


  然后考虑询问,

  

可以分块,

   

,逆向枚举每个合法的i,对其对应的倍数d加上

,分块的同时查询一下前缀和即可。

  

#include<cstdio>
#include<algorithm>
#define lowbit(x) ((-x)&x)
inline int read(){
int s=0;char ch=getchar();
while(ch>'9'||ch<'0')   ch=getchar();
while(!(ch>'9'||ch<'0'))  s=s*10+ch-48,ch=getchar();
return s;
}
inline int min(int a,int b){return a<b?a:b;}
const int N=(int )1e5+10;
int c
;
void   add(int x,int w){
for(int i=x;i<N;i+=lowbit(i))
c[i]+=w;
}
int query(int x){
int s=0;
for(int i=x;i;i-=lowbit(i))
s+=c[i];
return s;
}
int F
,mobius
;
int pri
,K,opt
,mar;
bool vis
;
inline void init(){
F[1]=1;mobius[1]=1;
opt[1]=1;
for(int i=2;i<mar;i++){
///   printf("%d\n",i);
if(!vis[i]) pri[++K]=i,F[i]=i+1,mobius[i]=-1;
for(int j=1;j<=K&&pri[j]*i<mar;j++){
vis[i*pri[j]]=1;
if(i%pri[j])    F[pri[j]*i]=F[i]*(pri[j]+1),mobius[pri[j]*i]=-mobius[i];
else{
int t=i;while(t%pri[j]==0)  t/=pri[j];
F[pri[j]*i]=F[i]*pri[j]+F[t];
mobius[pri[j]*i]=0;
break;
}
}
opt[i]=i;
}
}
int ans
;
int n
,m
,a
,ops
;
int T;
bool cmp(int x,int y){
return a[x]<a[y];
}
bool F_cmp(int x,int y){
return F[x]<F[y];
}
inline void solve(int x)
{
for (int i=1,pos;i<=n[ops[x]];i=pos+1)
{

pos=min(n[ops[x]]/(n[ops[x]]/i),m[ops[x]]/(m[ops[x]]/i));
ans[ops[x]]+=(n[ops[x]]/i)*(m[ops[x]]/i)*(query(pos)-query(i-1));
}
}
int main(){

T=read();
for(int i=1;i<=T;i++){
n[i]=read(),m[i]=read(),a[i]=read();
if(n[i]>m[i])   n[i]^=m[i]^=n[i]^=m[i];
ops[i]=i;mar=n[i]>mar?n[i]:mar;
}
mar++; init();
std::sort(ops+1,ops+1+T,cmp);
std::sort(opt+1,opt+mar,F_cmp);
int now=0;
for(int i=1;i<=T;i++){
while(F[opt[now+1]]<=a[ops[i]]){
for(int j=opt[++now];j<mar;j+=opt[now])
add(j,F[opt[now]]*mobius[j/opt[now]]);
}
solve(i);
}
for(int i=1;i<=T;i++){
printf("%d\n",ans[i]&0x7fffffff);
}
}


    

   

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: