[Sdoi2014]数表
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2383 Solved: 1229
[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
http://wenku.baidu.com/view/fbec9c63ba1aa8114431d9ac.html
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<set> 6 #include<ctime> 7 #include<vector> 8 #include<queue> 9 #include<algorithm> 10 #include<map> 11 #include<cmath> 12 #define inf 1000000000 13 #define pa pair<int,int> 14 #define ll long long 15 using namespace std; 16 int read() 17 { 18 int x=0,f=1;char ch=getchar(); 19 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 20 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 21 return x*f; 22 } 23 int Q,mx,cnt; 24 struct data{ 25 int n,m,a,id; 26 }q[40005]; 27 bool mark[100005]; 28 int pri[100005],mu[100005],t[100005]; 29 int ans[40005]; 30 pair<int,int> F[100005]; 31 bool operator<(data a,data b) 32 { 33 return a.a<b.a; 34 } 35 void add(int x,int val) 36 { 37 for(int i=x;i<=mx;i+=i&-i)t[i]+=val; 38 } 39 int query(int x) 40 { 41 int tmp=0; 42 for(int i=x;i;i-=i&-i)tmp+=t[i]; 43 return tmp; 44 } 45 void pre() 46 { 47 mu[1]=1; 48 for(int i=2;i<=mx;i++) 49 { 50 if(!mark[i])pri[++cnt]=i,mu[i]=-1; 51 for(int j=1;j<=cnt&&pri[j]*i<=mx;j++) 52 { 53 mark[pri[j]*i]=1; 54 if(i%pri[j]==0){mu[pri[j]*i]=0;break;} 55 else mu[pri[j]*i]=-mu[i]; 56 } 57 } 58 for(int i=1;i<=mx;i++) 59 for(int j=i;j<=mx;j+=i) 60 F[j].first+=i; 61 for(int i=1;i<=mx;i++)F[i].second=i; 62 } 63 void solve(int x) 64 { 65 int id=q[x].id,n=q[x].n,m=q[x].m; 66 for(int i=1,j;i<=q[x].n;i=j+1) 67 { 68 j=min(n/(n/i),m/(m/i)); 69 ans[id]+=(n/i)*(m/i)*(query(j)-query(i-1)); 70 } 71 } 72 int main() 73 { 74 Q=read(); 75 for(int i=1;i<=Q;i++) 76 { 77 q[i].n=read();q[i].m=read();q[i].a=read();q[i].id=i; 78 if(q[i].n>q[i].m)swap(q[i].n,q[i].m); 79 mx=max(mx,q[i].n); 80 } 81 pre(); 82 sort(q+1,q+Q+1); 83 sort(F+1,F+mx+1); 84 int now=0; 85 for(int i=1;i<=Q;i++) 86 { 87 while(now+1<=mx&&F[now+1].first<=q[i].a) 88 { 89 now++; 90 for(int j=F[now].second;j<=mx;j+=F[now].second) 91 add(j,F[now].first*mu[j/F[now].second]); 92 } 93 solve(i); 94 } 95 for(int i=1;i<=Q;i++) 96 printf("%d ",ans[i]&0x7fffffff); 97 }