一个人的数论:莫比乌斯反演,伯努利数

在做多项式的时候发现自己不会伯努利数,被推荐回来做这道题。

然后就发现这真的是个大神题,而且有一些思路很重要。

以后不能再漏题丢知识点了不然被迫填坑是真的难受。

 

题意式子:

$ \sum\limits_{i=1}^{N} \left[ gcd \left( i,N \right) =1 \right] i^d $

经典反演:

$=\sum\limits_{i=1}^{N} i^d \sum\limits_{j|i \ and \ j|N} \mu(j)$

$=\sum\limits_{j|N} \sum\limits_{i=1}^{\frac{N}{j}} (ij)^d \mu(j)$

$=\sum\limits_{j|N} \mu(j) j^d \sum\limits_{i=1}^{\frac{N}{j}}i^d$

后面是自然数幂和的公式。如果原来没有听说过伯努利数,那么你可以凭空猜测下列结论。

如果听说过伯努利数,那么你就知道对于确定的d,$\sum\limits_{i=1}^{n} i^d =\sum\limits_{i=0}^{d+1} a_i \times n^{i}$

其中$a_i$表示一个特定的系数,不随n变化而变化。事实证明这是正确的,我不会理论证明。

这样的话就得到了一个关于n的d+1次多项式,把求和的复杂度由与n相关变为了与d相关。(伯努利数的应用)

伯努利数是有公式的:$\sum\limits_{i=1}^{n} i^d = \frac{1}{d+1} \sum\limits_{i=0}^{d+1} C_{d+1}^{i} B_i n^{d+1-i} $

这样的话只要我们求解出伯努力数就可以得到上面的所有$a_i$值。

但是首先我们什么也不会,其次这题的数据范围很小,所以我们可以选择将d+1个x值带入上面的多项式进行瓜丝消元,就可以求解出所有$a_i$值。

那么自然数幂和的问题(假如)我们已经解决了。继续化简原式:

$=\sum\limits_{j|N} \mu(j) j^d \sum\limits_{i=0}^{d+1}(\frac{N}{j})^i \times a_i$

$=\sum\limits_{i=0}^{d+1} a_i \sum\limits_{j|N} \mu(j) \times j^d \times  (\frac{N}{j})^i$

$=\sum\limits_{i=0}^{d+1} a_i \times N^i \sum\limits_{j|N} \mu(j) \times j^{d-i}$

观察后面那个和式,它是两个积性函数相乘,依然是积性函数,而题目已经给出了质因数分解,这很方便。

再从含义出发,依次考虑每个质因子,只有在质因子的次数为0或1时对答案有贡献,其余时候$\mu(j)$均为0。

所以只用考虑1与p的和式值,然后因为是积性函数,所以对于每个质因子把结果相乘。

式子的最终形态:

$=\sum\limits_{i=0}^{d+1} a_i \times N^i \prod\limits_{j=1}^{w} (1-p_j^{d-i})$

确实是痛苦AC。感谢miku大神的指导。

 1 #include<cstdio>
 2 #define int long long
 3 #define mod 1000000007
 4 int d,w,fac[105],inv[105],N=1,p[1005],t[1005],mx[102][102],ans;
 5 int pow(int b,int t,int a=1){for(;t;t>>=1,b=b*b%mod)if(t&1)a=a*b%mod;return a;}
 6 void Gauss(){
 7     for(int i=1;i<=d+1;++i){
 8         int x=pow(mx[i][i],mod-2);
 9         for(int j=i;j<=d+2;++j)mx[i][j]=mx[i][j]*x%mod;
10         for(int j=i+1;j<=d+1;++j)for(int k=d+2;k>=i;--k)mx[j][k]=(mx[j][k]-mx[i][k]*mx[j][i]%mod+mod)%mod;
11     }
12     for(int i=d+1;i;--i)for(int j=i-1;j;--j)mx[j][d+2]=(mx[j][d+2]-mx[j][i]*mx[i][d+2]%mod+mod)%mod;
13 }
14 signed main(){
15     scanf("%lld%lld",&d,&w);fac[0]=1;
16     for(int i=1;i<=d;++i)fac[i]=fac[i-1]*i%mod;
17     inv[d]=pow(fac[d],mod-2);
18     for(int i=d-1;~i;--i)inv[i]=inv[i+1]*(i+1)%mod;
19     for(int i=1;i<=w;++i)scanf("%lld%lld",&p[i],&t[i]),N=N*pow(p[i],t[i])%mod;
20     for(int i=1;i<=d+1;++i)mx[i][d+2]=(mx[i-1][d+2]+pow(i,d))%mod,mx[i][1]=i;
21     for(int i=1;i<=d+1;++i)for(int j=2;j<=d+1;++j)mx[i][j]=mx[i][j-1]*i%mod;
22     Gauss();
23     for(int i=1;i<=d+1;++i){
24         int base=mx[i][d+2]*pow(N,i)%mod;
25         for(int j=1;j<=w;++j)base=base*(mod+1-pow(p[j],d-i+mod-1))%mod;
26         ans=(ans+base)%mod;
27     }printf("%lld\n",ans);
28 }
我直到现在才追上6个月以前的泥萌啊
posted @ 2019-12-10 06:29  DeepinC  阅读(388)  评论(3编辑  收藏  举报