莫比乌斯反演呓语
接下来介绍一种线性筛的做法来筛出莫比乌斯函数。 if (i % p[j] == 0)
这句话非常关键,也是为什么这个筛法是线性筛的原因。
同样把这个程序的μ[x]μ[x] 去掉就是单纯的质数筛,同样这个质数筛由于if (i % p[j] == 0)
的存在,也是一个线性筛。
void mobius() { int i,j; mbs[1] = 1; fo(i,2,N) { if (!vis[i]) {p[++p[0]] = i; mbs[i] = -1;} for (j = 1;j <= p[0] && i * p[j] <= N; j++) { vis[i*p[j]] = 1; if (i % p[j] == 0) {mbs[i*p[j]] = 0; break;} mbs[i*p[j]] = - mbs[i]; } } }
#include <bits/stdc++.h> using namespace std; const int MAXN = 100000; bool check[MAXN+10]; int prime[MAXN+10]; int mu[MAXN+10]; //求1-n,1-m内gcd=x(的倍数)的个数,修改可以改这个(大概,我还没试过) inline long long f(int n,int m,int x){ return (n/x)*(m/x); } void Moblus() { memset(check,false,sizeof(check)); mu[1] = 1; int tot = 0; for(int i = 2; i <= MAXN; i++) { if( !check[i] ) { prime[tot++] = i; mu[i] = -1; } for(int j = 0; j < tot; j ++) { if( i * prime[j] > MAXN) break; check[i * prime[j]] = true; if( i % prime[j] == 0) { mu[i * prime[j]] = 0; break; } else { mu[i * prime[j]] = -mu[i]; } } } } int sum[MAXN+10]; //找[1,n],[1,m]内互质的数的对数 long long solve(int n,int m) { long long ans = 0; if(n > m)swap(n,m); for(int i = 1, la = 0; i <= n; i = la+1) { la = min(n/(n/i),m/(m/i)); ans += (long long)(sum[la] - sum[i-1])*f(n,m,i); } return ans; } int main() { Moblus(); sum[0] = 0; for(int i = 1; i <= MAXN; i++) sum[i] = sum[i-1] + mu[i]; int a,b,c,d,k; int T; scanf("%d",&T); while(T--) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); long long ans = solve(b/k,d/k) - solve((a-1)/k,d/k) - solve(b/k,(c-1)/k) + solve((a-1)/k,(c-1)/k); printf("%lld\n",ans); } return 0; }
posted on 2018-08-14 11:56 Best_Efforts 阅读(145) 评论(0) 编辑 收藏 举报