bzoj2693

 

 

线性筛+莫比乌斯反演

盗波图 来自candy?大神

反演很重要的一条公式就是[gcd(i,j)==1]=

线性筛怎么推呢?

我们分4个步骤,1.先推出f[1],2.推出f[p],p是一个质数,3.由于线性筛筛的是积性函数,那么当gcd(i,p[j])==1的时候,f[i*p[j]]=f[i]*f[p[j]],4.前三步都比较简单,第四步是if(i%p[j]==0)该怎么办

我们是要推这个东西的值,因为积性函数的约数和也是积性函数,所以这个也可以筛,那么我们考虑对于当前的D,我们用一个pri筛到了D,而且D%pri==0,然后思考一下,这个pri能给这个式子带来什么贡献呢?

很明显,i肯定是几个质数的乘积,否则mu[i]==0,没有意义,那么这个pri肯定对约数和没有贡献了,因为之前筛到的时候已经被计算过了,那个*i^2自然也是不可能受到pri的影响,但是我们看看那个D,现在我们求的是f[D*pri],那么自然D得乘上pri,所以我们得出现在f[i*pri]=f[i]*pri

大概是这样吧

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 10000010, mod = 100000009;
int n, m, T;
int mu[N], p[N];
bool mark[N];
ll f[N];
void ini()
{
    mu[1] = f[1] = 1;
    for(int i = 2; i <= 10000000; ++i)
    {
        if(!mark[i])
        {
            p[++p[0]] = i;
            mu[i] = -1;
            f[i] = ((-(ll)i * (ll)i + i) % mod + mod) % mod;
        } 
        for(int j = 1; j <= p[0] && i * p[j] <= 10000000; ++j)
        {
            mark[i * p[j]] = 1;
            if(i % p[j] == 0)
            {
                mu[i * p[j]] = 0;
                f[i * p[j]] = f[i] * p[j] % mod;
                break;
            }
            f[i * p[j]] = f[i] * f[p[j]] % mod; 
            mu[i * p[j]] = -mu[i];
        }
    }
    for(int i = 1; i <= 10000000; ++i) f[i] = (f[i] + f[i - 1]) % mod;
}
ll Sum(ll x, ll y)
{
    return (x * (x + 1ll) / 2ll % mod) % mod * (y * (y + 1ll) / 2ll % mod) % mod;
}
void solve(int n, int m)
{
    if(n > m) swap(n, m);
    ll ret = 0;
    for(int i = 1, j = 0; i <= n; i = j + 1)
    {
        j = min(n / (n / i), m / (m / i));
        ret = (ret + Sum(n / i, m / i) % mod * ((f[j] - f[i - 1]) % mod + mod) % mod) % mod;
    }
    printf("%lld\n", ret);
}
int main()
{
    ini();
    for(cin >> T; T; --T)
    {
        scanf("%d%d", &n, &m);
        solve(n, m);
    }
    return 0;
}
View Code

 

posted @ 2017-09-15 12:11  19992147  阅读(150)  评论(0编辑  收藏  举报