题意 : 中文题目不解释
求gcd(x,y) = k (a<=x<=b, c<=y<=d);
根据gcd(ka,kb) = k*gcd(a,b), 可将问题转化为求gcd(a/k, b/k) = 1;
再由容斥定理可得到gcd(x,y) = gcd(b,d)- gcd(a,d)- gcd(c,b)+ gcd(a,c);
再套上莫比乌斯反演的模板, 嗯, 然后就能得到一次TE;
正解 : 容斥+莫比乌斯反演+分块优化;
分块优化 : 考虑到[n/i]、[m/i]都会有大量的完全相等的部分,我们可以把[n/i]、[m/i]都相等的部分放在一起算,也就是一个分块的思想。预处理出μ(d)的前缀和即可。
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ll long long const int maxn = 50005; ll pri[maxn], mu[maxn]; ll vis[maxn]; void init() { memset(vis, 0, sizeof(vis)); memset(mu, 0, sizeof(mu)); mu[1] = 1; int cnt = 0; for(ll i =2; i <= 50005; i++) { if(vis[i] == 0) {mu[i] = -1; pri[cnt++] = i;} for(ll j =0; j < cnt&&i*pri[j] <= 50005; j++) { ll k = i*pri[j]; vis[k] = 1; if(i%pri[j] == 0) {mu[k] = 0; break; } else mu[k] = -mu[i]; } } for(ll i = 2; i <= 50005; i++) // 前缀和处理mu; mu[i] += mu[i-1]; } ll cal(ll l, ll r) // 分块优化 { if(l > r) swap(l, r); ll ans = 0; ll hay = 0; for(ll i = 1; i <=l; i = hay+1) { hay = min(l/(l/i), r/(r/i) ); ans += (mu[hay] - mu[i-1])*(l/i)*(r/i); } return ans; } int main() { ios::sync_with_stdio(false); init(); ll n; cin >> n; while(n--) { ll a, b, c, d, k; cin >> a >> b >> c >> d >> k; ll ans = 0; ans = cal(b/k, d/k)+ cal((a-1)/k,(c-1)/k) - cal((a-1)/k, d/k)- cal((c-1)/k, b/k); printf("%lld\n", ans); } return 0; }