Description
FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a
,y<=b,并且gcd(x,y)=d。作为FGD的同学,FGD希望得到你的帮助。
Input
第一行包含一个正整数n,表示一共有n组询问。(1<=n<= 50000)接下来n行,每行表示一个询问,每行三个
正整数,分别为a,b,d。(1<=d<=a,b<=50000)
Output
对于每组询问,输出到输出文件zap.out一个正整数,表示满足条件的整数对数。
Sample Input
2
4 5 2
6 4 3
4 5 2
6 4 3
Sample Output
3
2
//对于第一组询问,满足条件的整数对有(2,2),(2,4),(4,2)。对于第二组询问,满足条件的整数对有(
6,3),(3,3)。
2
//对于第一组询问,满足条件的整数对有(2,2),(2,4),(4,2)。对于第二组询问,满足条件的整数对有(
6,3),(3,3)。
写多了发现全是套路...
就是需要一个前缀和优化...什么整除分块什么的,昨天晚上做了余数求和那道题貌似就是除法分块。
好高深。
还有为什么不开long long 比 开 块一倍多, 又是玄学?
开long longTLE了,换成int过了233
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; inline int read(){ int res=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();} return res; } int T, n, a, b, d; int prime[50005], miu[50005], cnt; bool vis[50005]; int qzh[50005]; signed main() { T = read(); n = 50000; miu[1] = 1; for (int i = 2 ; i <= n ; i ++) { if (!vis[i]) prime[++cnt] = i, miu[i] = -1; for (int j = 1 ; j <= cnt and i * prime[j] <= n ; j ++) { vis[i*prime[j]] = 1; if (i % prime[j] == 0) break; miu[i*prime[j]] = - miu[i]; } } for (int i = 1 ; i <= n ; i ++) qzh[i] = qzh[i-1] + miu[i]; while(T--) { a = read(), b = read(), d = read(); int ans = 0; a=a/d, b=b/d; for (int i = 1, gx ; i <= min(a, b) ; i = gx + 1) { gx = min(a/(a/i), b/(b/i)); ans += (a/i)*(b/i)*(qzh[gx]-qzh[i-1]); } printf("%d\n", ans); } return 0; }