1. 程式人生 > >【BZOJ3309】DZY Loves Math(莫比烏斯反演)

【BZOJ3309】DZY Loves Math(莫比烏斯反演)

namespace ... ++ bre getchar stream 那種 getc 分解質

【BZOJ3309】DZY Loves Math(莫比烏斯反演)

題面


\[\sum_{i=1}^a\sum_{j=1}^bf(gcd(a,b))\]
其中,\(f(x)\)表示\(x\)分解質因數之後,最高的冪次

題解

完全不會莫比烏斯反演了。
先來推式子
\[\sum_{d=1}^a\sum_{i=1}^{a/d}\sum_{j=1}^{b/d}[gcd(i,j)=1]f(d)\]
\[\sum_{d=1}^af(d)\sum_{i=1}^{a/d}\sum_{j=1}^{b/d}[gcd(i,j)=1]\]
\(F(x)=\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=x]\)


\(G(x)=\sum_{x|d}f(d)=\sum_{i=1}^n\sum_{j=1}^m[x|gcd(i,j)]\)
所以\(G(x)=[\frac{n}{x}][\frac{m}{x}]\)
所以原式可以變為
又有\(F(x)=\sum_{x|d}\mu(\frac{d}{x})G(d)\)
所以\(F(1)=\sum_{d=1}^n\mu(d)G(d)\)
所以所求變為
\[\sum_{d=1}^af(d)\sum_{i=1}^{a/d}\mu(i)G(i)\]
\[\sum_{d=1}^af(d)\sum_{i=1}^{a/d}\mu(i)[\frac{a}{id}][\frac{b}{id}]\]

老套路了,令\(T=id\)
\[\sum_{T=1}^a[\frac{a}{T}][\frac{b}{T}]\sum_{d|T}f(d)\mu(\frac{T}{d})\]
後面這個玩意怎麽算呢??
迷茫啊。。。。

考慮枚舉的每一個\(T=p1^{a1}*p2^{a2}...pn^{an}\)
因為\(\mu\)要非零才有貢獻,所以\(\frac{T}{d}\)的每一個質因數最多取\(1\),因此一共有\(2^n\)個對應的\(d\)
假設確定了選擇某個質因數\(px^{ax-1}\),並且它是最高冪了
那麽所有比它低的冪次都可以隨意選或者不選,
一共是\(2^{?-1}\)個,不難證明此時\(f(d)\)

的值一樣,\(\mu\)的值恰好一一對應為\(-1,1\),此時的和一定為\(0\)
這樣的前提是存在比他低的次冪,也就意味著所有的冪次不全相等。

假設全部相等的時候?
也就是\(T=(p1p2p3..pn)^a\)
\(d=(p1p2..pn)^{a-1}\)時,\(f(d)=a-1\)
其他情況下\(f(d)=a\)
先假設所有情況下\(f(d)=a\)
顯然最終的和也是\(0\)
但是有一種情況下為\(a-1\),因此要對於上面那種情況額外把\(1\)減掉
因此貢獻是\(-1*\mu(p1p2p3..pn)=(-1)^{(n+1)}\)

這樣就可以算出後面那一坨東西的值了。
至於怎麽線性篩?
額外記錄每個數出去最小質因子後的數\(lst[i]\)
以及最小質因子的冪次
這樣就可以通過\(lst[i]\)計算出結果了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 10000000
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
bool zs[MAX+1];
int pri[MAX+1],tot,g[MAX+1],lst[MAX+1],fp[MAX+1];
void pre()
{
    for(int i=2;i<=MAX;++i)
    {
        if(!zs[i])pri[++tot]=i,lst[i]=g[i]=fp[i]=1;
        for(int j=1;j<=tot&&i*pri[j]<=MAX;++j)
        {
            int x=i*pri[j];
            zs[x]=true;
            if(i%pri[j]==0)
            {
                lst[x]=lst[i];
                fp[x]=fp[i]+1;
                if(lst[x]==1)g[x]=1;
                else g[x]=(fp[lst[x]]==fp[x]?-g[lst[x]]:0);
                break;
            }
            lst[x]=i;fp[x]=1;g[x]=(fp[i]==1?-g[i]:0);
        }
    }
    for(int i=1;i<=MAX;++i)g[i]+=g[i-1];
}
int main()
{
    pre();
    int T=read();
    while(T--)
    {
        int a=read(),b=read();
        if(a>b)swap(a,b);
        ll ans=0;
        for(int i=1,j;i<=a;i=j+1)
        {
            j=min(a/(a/i),b/(b/i));
            ans+=1ll*(a/i)*(b/i)*(g[j]-g[i-1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

【BZOJ3309】DZY Loves Math(莫比烏斯反演)