题目
思路
令
枚举 ,我们可以写出
再令
我们此时可以进行莫比乌斯反演(或者叫容斥),得到
枚举 的值,写成
显然前面可以整除分块了,要做的就是求出 的前缀和。
考虑使用 线性筛。这个函数是个积性函数,因为,记 ,则
至于 的值怎么计算呢,如果 的话?考虑到 的存在使得质因数指数不超过 ,所以贡献不为零的约数 没有增加。唯一需要的是 变成了原来的 倍,相乘即可。
代码
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
typedef long long int_;
int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0'||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
template < typename T >
void getMin(T&a,const T&b){ if(b<a)a=b; }
const int MaxN = 10000005;
const int zxy = 100000009;
bool isPrime[MaxN];
int f[MaxN], mu[MaxN];
vector< int > primes;
void sievePrime(int n){
f[1] = mu[1] = 1;
for(int i=2; i<=n; ++i)
isPrime[i] = true;
for(int i=2,len=0; i<=n; ++i){
if(isPrime[i]){
primes.push_back(i);
mu[i] = -1, ++ len;
f[i] = (i-1ll*i*i)%zxy;
}
for(int j=0; j<len; ++j){
if(primes[j] > n/i) break;
isPrime[i*primes[j]] = 0;
if(i%primes[j] == 0){
mu[i*primes[j]] = 0;
f[i*primes[j]] = 1ll*
f[i]*primes[j]%zxy;
break;
}
mu[i*primes[j]] = -mu[i];
f[i*primes[j]] = 1ll*f[i]
*f[primes[j]]%zxy;
}
}
}
int S(int a,int b){
a = (1ll*a*(a+1)>>1)%zxy;
b = (1ll*b*(b+1)>>1)%zxy;
return 1ll*a*b%zxy;
}
int main(){
sievePrime(MaxN-5);
for(int i=2; i<=MaxN-5; ++i)
f[i] = (f[i]+f[i-1]+zxy)%zxy;
for(int T=readint(); T; --T){
int n = readint();
int m = readint();
int ans = 0;
if(n > m) swap(n,m);
for(int l=1,r; l<=n; l=r+1){
r = min(n/(n/l),m/(m/l));
int_ now = f[r]-f[l-1];
now = (now%zxy+zxy)%zxy;
now = now*S(n/l,m/l)%zxy;
ans = (ans+now)%zxy;
}
printf("%lld\n",ans);
}
return 0;
}