hdu 1695 GCD(莫比乌斯反演)

来源:互联网 发布:网络通信公司简介 编辑:程序博客网 时间:2024/05/14 11:03

设f(d)为gcd(x,y) ==k, 0<x<n , 0<y<m的个数

设F(d)为gcd(x,y)|d的个数

那么利用莫比乌斯反演公式直接求解即可,sqrt(n)的复杂度,面对三千组数据还是够的

注意long long 的使用,作为一个水笔,我竟然int了一发,wa的死死的

#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#define MAX 150007using namespace std;typedef long long LL;LL t,a,b,c,d,k;int prime[MAX];int cnt;int mu[MAX];int vis[MAX];void init ( ){    memset ( vis , 0 , sizeof ( vis ) );    cnt = 0;    mu[1] = 1;    for ( int i = 2 ; i < MAX ; i++ )    {        if ( !vis[i] )        {            prime[cnt++] = i;            mu[i] = -1;        }        for ( int j = 0 ; j < cnt && i*prime[j] < MAX ; j++ )        {            vis[i*prime[j]] = 1;            if ( i%prime[j] ) mu[i*prime[j]] = -mu[i];            else            {                mu[i*prime[j]] = 0;                break;            }        }    }}LL get ( LL n , LL m , LL k ){    if ( n > m ) swap ( n , m );    return (n/k)*(n/k+1)/2 + ((m-(n/k)*k)/k)*(n/k); }int main ( ){    scanf ( "%lld" , &t );    init ( );    int cc = 1;    while ( t-- )    {        scanf ( "%lld%lld%lld%lld%lld" , &a , &b , &c , &d , &k );        LL ans = 0;        int lim = min ( b , d );        printf ( "Case %d: " , cc++ );        if ( k == 0 )        {            puts ( "0" );            continue;        }        for ( int i = k ; i<= lim ; i += k )            ans += (LL)(mu[i/k])*(LL)(get( b , d , i));        printf ( "%I64d\n" , ans );    }}


0 0