【莫比乌斯反演】【数论】[ZBOJ 2693]jzptab
这个公式的由来详见:http://blog.csdn.net/jeremygjy/article/details/50592588
这道题目就是Crash的数表的强化版本,因为有多组数据那么
这里说一下怎么处理前缀和的问题:
首先我们令当前的数字是
不包含
如果i′p 中我们选择的i 不包含i′ 那么可以发现有Ds(i′p)=i′×Ds(p) 因为主要是因为由Ds(p)=∑i|pipμ(i) 现在变成了Ds(p)=∑i|pipi′μ(i) 根据分配律展开就行了,那么如果包含i′ 呢?包含
如果i′p 中我们选择的i 包含i′ 那么有由Ds(p)=∑i|pipμ(i) 现在变成了Ds(p)=∑i|p(ii′)(pi′)μ(ii′) 因为μ(ii′)=μ(i)μ(i′)=−μ(i) 所以现在的就变成了Ds(i′p)=−Ds(p)×(i′)2
综上所述
但是如果对于一个数中已经含有因数
#include <cstdio>
#include <iostream>
#include <cstring>
#include <climits>
#include <algorithm>
using namespace std;
#define mod 100000009
const int MAXN = 10001000;
bool notprime[MAXN+10];
int prime[MAXN+10], sum[MAXN+10], Max;
long long Ds[MAXN+10];
void Init(){
Ds[1] = 1;
int tmp;
for(int i=2;i<=Max;i++){
if(!notprime[i]){
Ds[i] = (i - (1LL * i * i)%mod)%mod;
prime[++prime[0]] = i;
}
for(int j=1;j<=prime[0]&&(tmp=prime[j]*i)<=Max;j++){
notprime[tmp] = true;
if(i%prime[j] == 0){
Ds[tmp] = prime[j] * Ds[i];
break;
}
Ds[tmp] = (Ds[i] * prime[j] - Ds[i] * prime[j] * prime[j] % mod) %mod;
}
}
for(int i=1;i<=Max;i++){
Ds[i] += Ds[i-1];
Ds[i] %= mod;
}
}
long long Sum(long long a, long long b){
return (a*(a+1)/2%mod) * (b*(b+1)/2%mod)%mod;
}
void solve(int n, int m, long long &ans){
int last;
ans = 0;
for(long long i=1;i<=n;i=last+1){
last = min(n/(n/i), m/(m/i));
ans += 1LL * (Ds[last] - Ds[i-1]) * Sum((1LL*n/i) , (1LL*m/i)) % mod;
ans %= mod;
}
}
int main(){
int T, n, m;
scanf("%d", &T);
Max = 10000000;
Init();
long long ans;
for(int i=1;i<=T;i++){
scanf("%d%d", &n, &m);
if(n > m) swap(n, m);
solve(n, m, ans);
printf("%lld\n", (ans%mod+mod)%mod);
}
return 0;
}