2301: [HAOI2011]Problem b
Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 1047 Solved: 434
[Submit][Status]
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
题解:
其实就是容斥原理了
代码:
1 uses math; 2 const maxn=55000; 3 var i,n,a,b,c,d,w,tot:longint; 4 ans:int64; 5 sum,mu,p:array[0..maxn] of int64; 6 procedure get; 7 var i,j,k:longint; 8 check:array[0..maxn] of boolean; 9 begin 10 fillchar(check,sizeof(check),false); 11 tot:=0;mu[1]:=1; 12 for i:=2 to maxn do 13 begin 14 if not(check[i]) then begin inc(tot);p[tot]:=i;mu[i]:=-1;end; 15 for j:=1 to tot do 16 begin 17 k:=i*p[j]; 18 if k>maxn then break; 19 check[k]:=true; 20 if i mod p[j]<>0 then mu[k]:=-mu[i] 21 else begin mu[k]:=0;break;end; 22 end; 23 end; 24 for i:=1 to maxn do sum[i]:=sum[i-1]+mu[i]; 25 end; 26 function f(x,y:longint):int64; 27 var i,last,t:longint; 28 begin 29 x:=x div w;y:=y div w; 30 f:=0; 31 if x>y then begin t:=x;x:=y;y:=t;end; 32 i:=1; 33 while i<=x do 34 begin 35 last:=min(x div (x div i),y div (y div i)); 36 inc(f,(sum[last]-sum[i-1])*(x div i)*(y div i)); 37 i:=last+1; 38 end; 39 exit(f); 40 end; 41 procedure main; 42 begin 43 get; 44 readln(n); 45 for i:=1 to n do 46 begin 47 readln(a,b,c,d,w); 48 ans:=0; 49 inc(ans,f(b,d)); 50 dec(ans,f(a-1,d)); 51 dec(ans,f(b,c-1)); 52 inc(ans,f(a-1,c-1)); 53 writeln(ans); 54 end; 55 end; 56 begin 57 main; 58 end. 59
不知道为什么上面的数组都要开int64才能过,我觉得不需要啊,他们存储的值都在50000以内啊……????