SPOJ 4491 Primes in GCD Table(莫比乌斯反演)

来源:互联网 发布:景区系统源码 编辑:程序博客网 时间:2024/05/18 09:08

题意:求[1,m]和[1,n]中gcd为素数的数对数量。

思路:这道题和hdu 4746有点像 

传送门:http://blog.csdn.net/u014664226/article/details/48495375

思路大致相同,处理出每一项的系数,然后求前缀和分段加速。

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<queue>#include<stack>#include<string>#include<map>#include<set>#include<ctime>#define eps 1e-6#define LL long long#define pii pair<int, int>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;const int MAXN = 10000100;bool check[MAXN+10];int prime[MAXN+10];int mu[MAXN+10], F[MAXN+10];LL Sum[MAXN];void Moblus(){    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];            }        }    }    for(int i = 0; i < tot; i++) {for(int j = prime[i]; j < MAXN; j += prime[i]) {F[j] += mu[j/prime[i]];}    }    for(int j = 1; j <= MAXN; j++) Sum[j] = Sum[j-1] + F[j];} int main() {    //freopen("input.txt", "r", stdin);Moblus(); int T, a, b; cin >> T;while(T--) {scanf("%d%d", &a, &b);LL ans = 0;int t = min(a, b), last;for(int i = 1; i <= t; i = last+1) {last = min(a/(a/i), b/(b/i));ans += (LL)(Sum[last]-Sum[i-1])*(a/i)*(b/i);}printf("%lld\n", ans);}    return 0;}

0 0