《牛客练习赛72C》

莫比乌斯函数的重要性质:

mu[ij] = mu[i] * mu[j]  // gcd(i,j) = 1

mu[ij] = 0//gcd(i,j) != 1

然后就可以推了。

推到:$ans = \sum_{i = 1}^{n} \mu (i) \sum_{j = 1}^{n} \mu (j) \sum_{d | gcd(i,j)}^{} \mu (d)  $

然后改成枚举因子推还是很简单的。

然后推到因子的式子之后就想着一直怎么求了。

这里的话,其实是考虑n -> n+1多了的贡献,这样转移很快。

观察后可以发现,多了的贡献都是因子带来的。

所以每次转移只需要去计算因子的贡献即可,复杂度就能保证了。

然后注意因子去维护sum,动态维护。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<double,int> pii;
const int N = 5e4+5;
const int M = 1e6+5;
const LL Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e18
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
}
using namespace FASTIO;

LL mu[N],sum[N],ans[N];
int prime[N],tot = 0;
bool vis[N];
void init()
{
    mu[1] = 1;
    for(int i = 2;i < N;++i)
    {
        if(!vis[i])
        {
            prime[++tot] = i;
            mu[i] = -1;
        }
        for(int j = 1;j <= tot && prime[j] * i < N;++j)
        {
            vis[i * prime[j]] = 1;
            if(i % prime[j] == 0) break;
            else mu[i * prime[j]] = -mu[i];
        }
    }
}
void solve()
{
    ans[1] = 1,sum[1] = 1;
    for(int i = 2;i < N;++i)
    {
        ans[i] = ans[i - 1];
        int m = sqrt(i);
        for(int j = 1;j <= m;++j)
        {
            if(i % j == 0)
            {
                ans[i] += 2 * mu[j] *(mu[i] * sum[j] + mu[i] * mu[i]);
                sum[j] += mu[i];
                if(i / j != j)  
                {
                    ans[i] += 2 * mu[i / j] *(mu[i] * sum[i / j] + mu[i] * mu[i]); 
                    sum[i / j] += mu[i];
                }
            }
        }
    }
//    for(int i = 1;i <= 10;++i) dbg(ans[i]);
}
int main()
{
    init();
    solve();
    int ca;ca = read();
    while(ca--)
    {
        int n;n = read();
        printf("%lld\n",ans[n]);
    }    
    //system("pause");
    return 0;
}
View Code

 

posted @ 2020-11-07 20:00  levill  阅读(134)  评论(0编辑  收藏  举报