《牛客练习赛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; }