P3455 [POI2007]ZAP-Queries
这是一道比较简单的莫反题,还记得某巨巨说过,可以用莫比乌斯反
演解决的问题绝大部分都可以用
然而我太菜了
即:
也就是:
然后:
于是我们发现后面的的那堆平方可以
块就可以求出来了
蒟蒻的代码
#include<iostream>
#include<cstdio>
using namespace std;
#define Mod 20101009
#define Min(x,y) x>y?y:x
#define N 10000055
#define int long long
int mu[N] , g[N] , vis[N] , p[N] ;
int num ;
void Init(int x)
{
mu[1] = 1 ;
g[1] = 1 ;
for(int i = 2 ; i <= x ; i++ ){
if( !vis[i] ) p[++num] = i , mu[i] = -1 ;
for(int j = 1 ; j <= num && p[j] * i <= x ; j++ ){
vis[ p[j] * i ] = 1 ;
if( i % p[j] == 0 ) break ;
mu[ p[j] * i ] = -mu[i] ;
}
g[i] = ( g[ i - 1 ] + 1ll*i * i % Mod * ( mu[i] + Mod ) ) % Mod ;
}
return ;
}
int Sum(int x )
{
return ( ( x + 1 ) * x / 2 ) % Mod ;
}
int Ask(int x ,int y)
{
int ans = 0 ;
if( x > y ) swap( x , y ) ;
for(int l = 1 , r ; l <= x ; l = r + 1 ){
r = Min( x / ( x / l ) , y / ( y / l ) ) ;
ans = ( ans + 1ll*( g[r] - g[l - 1] + Mod ) % Mod * ( Sum( x / l ) * Sum( y / l ) ) % Mod ) % Mod ;
}
return ans % Mod ;
}
signed main()
{
int n , m ;
scanf("%lld%lld" , &n , &m ) ;
if( n > m ) swap( n , m ) ;
Init(m+10) ;
long long ans = 0 ;
for(int l = 1 , r ; l <= n ; l = r + 1 ){
r = Min( n / ( n / l ) , m / ( m / l ) ) ;
ans = ( ans + 1ll * ( 1ll * ( r - l + 1 ) * ( l + r ) / 2 ) % Mod * Ask( n / l , m / l ) % Mod ) % Mod ;
}
printf("%lld\n" , ans % Mod ) ;
}