3529: [Sdoi2014]数表
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2294 Solved: 1166
[Submit][Status][Discuss]
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
4 4 3
10 10 5
Sample Output
20
148
148
HINT
1 < =N.m < =10^5 , 1 < =Q < =2×10^4
Source
1 #include<bits/stdc++.h> 2 #define reg register 3 #define N 100001 4 using namespace std; 5 int cas,pos,now,cnt,ans[N],c[N],mo[N],p[N],vis[N]; 6 struct query{int n,m,a,id;}q[N];struct info{int v,p;}f[N]; 7 bool cmp1(info a,info b){return a.v<b.v;} 8 bool cmp2(query a,query b){return a.a<b.a;} 9 void update(int x,int v){while(x<N){c[x]+=v;x+=x&-x;}} 10 int query(int x){int ret=0;while(x){ret+=c[x];x-=x&-x;}return ret;} 11 int main(){ 12 mo[1]=1; 13 for(reg int i=2;i<N;++i){ 14 if(!vis[i]){p[++cnt]=i;mo[i]=-1;} 15 for(reg int j=1;j<=cnt&&p[j]*i<N;++j){ 16 vis[p[j]*i]=1; 17 if(i%p[j])mo[i*p[j]]=-mo[i]; 18 else{mo[i*p[j]]=0;break;} 19 } 20 } 21 for(reg int i=1;i<N;++i){ 22 for(reg int j=i;j<N;j+=i) 23 f[j].v+=i;f[i].p=i; 24 } 25 sort(f+1,f+N,cmp1); 26 scanf("%d",&cas); 27 for(reg int i=1;i<=cas;q[i].id=i,++i) 28 scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].a); 29 sort(q+1,q+1+cas,cmp2);++now; 30 for(reg int c=1;c<=cas;++c){ 31 while(now<N&&f[now].v<=q[c].a){ 32 for(reg int i=f[now].p;i<N;i+=f[now].p) 33 update(i,f[now].v*mo[i/f[now].p]); 34 ++now; 35 } 36 int id=q[c].id,n=q[c].n,m=q[c].m;if(n>m)swap(n,m); 37 for(int reg i=1;i<=n;i=pos+1){ 38 pos=min(n/(n/i),m/(m/i)); 39 ans[id]+=(n/i)*(m/i)*(query(pos)-query(i-1)); 40 } 41 } 42 for(int i=1;i<=cas;i++)printf("%d\n",ans[i]&0x7fffffff); 43 return 0; 44 }