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
【思路】
UPD:求a只和F(1..a)有关系改为:求a只和F(i)<=a的项有关系
自然溢出,最后and 2^31-1
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int N = 1e5+10; 7 8 struct Node { 9 int n,m,a,id; 10 bool operator< (const Node& rhs) const{ 11 return a<rhs.a; 12 } 13 }; 14 struct Fnode{ 15 int num,id; 16 bool operator<(const Fnode& rhs) const{ 17 return num<rhs.num; 18 } 19 }; 20 21 int mx,n,m,a; 22 int mu[N],su[N],sz,np[N],C[N],ans[N]; 23 Node que[N]; Fnode F[N]; 24 25 void add(int x,int v) 26 { 27 for(;x<=mx;x+=x&-x) C[x]+=v; 28 } 29 int query(int x) 30 { 31 int res=0; 32 for(;x;x-=x&-x) res+=C[x]; 33 return res; 34 } 35 36 void get_mu() 37 { 38 int i,j; 39 mu[1]=1; 40 for(i=2;i<=mx;i++) { 41 if(!np[i]) 42 mu[i]=-1,su[++sz]=i; 43 for(j=1;j<=sz&&i*su[j]<=mx;j++) { 44 np[i*su[j]]=1; 45 if(i%su[j]==0) 46 mu[i*su[j]]=0; 47 else 48 mu[i*su[j]]=-mu[i]; 49 } 50 } 51 } 52 void get_F() 53 { 54 int i,j; 55 for(i=1;i<=mx;i++) { 56 for(j=i;j<=mx;j+=i) 57 F[j].num+=i; 58 } 59 for(i=1;i<=mx;i++) F[i].id=i; 60 } 61 62 int main() 63 { 64 int T; 65 scanf("%d",&T); 66 for(int i=1;i<=T;i++) { 67 scanf("%d%d%d",&n,&m,&a); 68 if(n>m) swap(n,m); 69 que[i]=(Node){n,m,a,i}; 70 mx=max(mx,n); 71 } 72 get_mu(); get_F(); 73 sort(que+1,que+T+1); 74 sort(F+1,F+mx+1); 75 int now=0; 76 for(int i=1;i<=T;i++) { 77 while(now+1<=mx&&F[now+1].num<=que[i].a) { 78 now++; 79 for(int j=F[now].id;j<=mx;j+=F[now].id) 80 add(j,F[now].num*mu[j/F[now].id]); 81 } 82 int id=que[i].id,last; n=que[i].n,m=que[i].m; 83 for(int j=1;j<=n;j=last+1) { 84 last=min(n/(n/j),m/(m/j)); 85 ans[id]+=(query(last)-query(j-1))*(n/j)*(m/j); 86 } 87 } 88 for(int i=1;i<=T;i++) 89 printf("%d ",ans[i]&0x7fffffff); 90 return 0; 91 }