2301: [HAOI2011]Problem b
Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 1737 Solved: 749
[Submit][Status][Discuss]
Description
对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
Input
第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k
Output
共n行,每行一个整数表示满足要求的数对(x,y)的个数
Sample Input
2
2 5 1 5 1
1 5 1 5 2
2 5 1 5 1
1 5 1 5 2
Sample Output
14
3
HINT
100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000
Source
题解:一个霸(dou)气(bi)的莫比乌斯反演,然后没啥了,开始瞎搞——不过这题里面有个重要的思想——既然直接求某“悬空”区间的结果(“悬空”区间即像本题中第一个值设定为[a,b],而不是(0,b]),那么为何不用好求的求出来然后容斥原理加加减减呢——嗯哼么么哒
1 const maxn=150000; 2 var 3 i,j,k,l,m,n,x1,y1,x2,y2,z:longint; 4 a,b:array[0..maxn] of longint; 5 procedure swap(var x,y:longint); 6 var z:longint; 7 begin 8 z:=x;x:=y;y:=z; 9 end; 10 function doit(x,y:longint):int64; 11 var i,j,k:longint; 12 begin 13 doit:=0; 14 if x>y then swap(x,y); 15 if x=0 then exit(0); 16 i:=1; 17 while i<=x do 18 begin 19 if (x div (x div i))<(y div (y div i)) then 20 k:=x div (x div i) 21 else k:=y div (y div i); 22 inc(doit,(b[k]-b[i-1])*int64(x div i)*int64(y div i)); 23 i:=k+1; 24 end; 25 end; 26 begin 27 for i:=2 to maxn do 28 begin 29 if a[i]<>0 then continue; 30 for j:=i to maxn div i do a[i*j]:=i; 31 end; 32 b[1]:=1; 33 for i:=2 to maxn do 34 if a[i]=0 then b[i]:=-1 else 35 if ((i div a[i]) mod a[i])=0 then b[i]:=0 else 36 b[i]:=-b[i div a[i]]; 37 for i:=2 to maxn do b[i]:=b[i]+b[i-1]; 38 readln(n); 39 for i:=1 to n do 40 begin 41 readln(x1,y1,x2,y2,z); 42 x1:=(x1-1) div z;y1:=y1 div z; 43 x2:=(x2-1) div z;y2:=y2 div z; 44 writeln(doit(y1,y2)-doit(x1,y2)-doit(y1,x2)+doit(x1,x2)); 45 end; 46 readln; 47 end.