zoukankan      html  css  js  c++  java
  • 【bzoj3601】一个人的数论(莫比乌斯反演+拉格朗日插值)

    传送门

    题意:
    求$$
    sum_{i=1}^{n}i^d[gcd(i,n)=1]

    [ 思路: 我们对上面的式子进行变换,有: ]

    egin{aligned}
    &sum_{i=1}^{n}i[gcd(i,n)=1]
    =&sum_{i=1}^{n}isum_{x|gcd(i,n)}mu (x)
    =&sum_{i=1}^n isum_{x|i,x|n}mu(x)
    =&sum_{x|n}mu(x)x^dsum_{i=1}^{frac{n}{x}}i^d
    end{aligned}

    [ 以上都是一些套路,接下来才步入正题。 因为形如$sum_{i=1}^n i^d$这种都是一个以$n$为自变量的,最高项次数为$d+1$的多项式。 到这步后,我们将后面的形式化,即将多项式表示出来,设$a_i$为相关系数,那么就有式子等于: ]

    sum_{x|n}mu(x)x^dsum_{i=0}^{d+1}a_ilfloorfrac{n}{x} floor^i

    [变化一下有: ]

    sum_{i=0}^{d+1}a_isum_{x|n}mu(x)x^dlfloorfrac{n}{x} floor^i

    [ 这里面前面的$a_i$为多项式的系数,是未知的。 但其实因为我们知道多项式的形式为$sum_{i=0}^{d+1}a_ix^i$,我们可以直接把$x=1,x=2,cdots,x=d+1$的值求出来,然后高斯消元求解系数。 这里也可以利用拉格朗日插值来求解,代码是直接抄[yyb](https://www.cnblogs.com/cjyyb/p/10503174.html)(orz)的,思路应该是利用一下等式来求系数: ]

    sum_{i=0}^n y_iprod_{i!=j}frac{x-x_j}{x_i-x_j}

    [ 那么现在主要就是后面一部分的计算,我们令$f(x)=mu(x)x^d,g(x)=x^i$,那么后面一部分可以写为:$sum_{x|n}f(x)g(frac{n}{x})$,这是狄利克雷卷积的的形式,因为$f,g$都为积性,那么$h=f*g(n)$也为积性。 所以$h(n)=sum_{x|n}mu(x)x^dlfloorfrac{n}{x} floor^i$也为积性函数,那么我们可以考虑单独素因子的贡献。显然每个素因子只会出现$0$次或者$1$次,否则贡献为$0$,那么有: ]

    egin{aligned}
    h(p^a)&=sum_{j=0}^{a}mu(p^j)p^{jd}(frac{p^a}{p^j})^i
    &=p^{ai}-p^{ai}p^{d-i}
    end{aligned}

    [ 那么对于每个$i,0leq ileq d+1$,求出相应的$h(n)$,再与系数相乘最终结果就出来了。 感觉解法中将多项式形式化出来的想法很巧妙!没想到多项式还能这么用hhh,直接求解多项式的系数也是之前没想到的。之后对卷积的观察也很重要。 很好的一个题。细节参考代码: ```cpp /* * Author: heyuhhh * Created Time: 2019/11/21 19:44:08 */ #include <bits/stdc++.h> #define MP make_pair #define fi first #define se second #define sz(x) (int)(x).size() #define all(x) (x).begin(), (x).end() #define INF 0x3f3f3f3f #define Local #ifdef Local #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0) void err() { std::cout << ' '; } template<typename T, typename...Args> void err(T a, Args...args) { std::cout << a << ' '; err(args...); } #else #define dbg(...) #endif void pt() {std::cout << ' '; } template<typename T, typename...Args> void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); } using namespace std; typedef long long ll; typedef pair<int, int> pii; //head const int N = 1000 + 5, MOD = 1e9 + 7; ll qpow(ll a, ll b) { ll ans = 1; while(b) { if(b & 1) ans = ans * a % MOD; a = a * a % MOD; b >>= 1; } return ans; } //求d次多项式系数 struct Lagrange { ll f[N], a[N], b[N]; int d; void init(int _d) { d = _d; //y_i for(int i = 1; i <= d + 1; i++) f[i] = (f[i - 1] + qpow(i, d - 1)) % MOD; b[0] = 1; } void work() { for(int i = 0; i <= d; i++) { for(int j = i + 1; j; j--) b[j] = (b[j - 1] + MOD - 1ll * b[j] * (i + 1) % MOD) % MOD; b[0] = 1ll * b[0] * (MOD - i - 1) % MOD; } for(int i = 0; i <= d; i++) { int s = f[i + 1], inv = qpow(i + 1, MOD - 2); for(int j = 0; j <= d; j++) if(i != j) s = 1ll * s * qpow((i - j + MOD) % MOD, MOD - 2) % MOD; b[0] = 1ll * b[0] * (MOD - inv) % MOD; for(int j = 1; j <= d + 1; j++) b[j] = (MOD - 1ll * (b[j] + MOD - b[j - 1]) * inv % MOD) % MOD; for(int j = 0; j <= d + 1; j++) a[j] = (a[j] + 1ll * s * b[j]) % MOD; for(int j = d + 1; j; j--) b[j] = (b[j - 1] + MOD - 1ll * b[j] * (i + 1) % MOD) % MOD; b[0] = 1ll * b[0] * (MOD - i - 1) % MOD; } } }A; int d, w; ll prod[N]; void run(){ A.init(d + 1); A.work(); for(int i = 0; i <= d + 1; i++) prod[i] = 1; while(w--) { int p, a; cin >> p >> a; for(int i = 0; i <= d + 1; i++) { ll res = (qpow(p, 1ll * a * i) - qpow(p, 1ll * a * i + d) * qpow(qpow(p, i), MOD - 2) % MOD + MOD) % MOD; prod[i] = prod[i] * res % MOD; } } ll ans = 0; for(int i = 0; i <= d + 1; i++) ans = (ans + A.a[i] * prod[i] % MOD) % MOD; cout << ans << ' '; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cout << fixed << setprecision(20); while(cin >> d >> w) run(); return 0; } ```]

  • 相关阅读:
    Java.io.outputstream.PrintStream:打印流
    Codeforces 732F. Tourist Reform (Tarjan缩点)
    退役了
    POJ 3281 Dining (最大流)
    Light oj 1233
    Light oj 1125
    HDU 5521 Meeting (最短路)
    Light oj 1095
    Light oj 1044
    HDU 3549 Flow Problem (dinic模版 && isap模版)
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11909180.html
Copyright © 2011-2022 走看看