设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 150007
using 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 );
}
}