在做多项式的时候发现自己不会伯努利数,被推荐回来做这道题。
然后就发现这真的是个大神题,而且有一些思路很重要。
以后不能再漏题丢知识点了不然被迫填坑是真的难受。
题意式子:
$ \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=1}^{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} 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=1}^{d+1}(\frac{N}{j})^i \times a_i$
$=\sum\limits_{i=1}^{d+1} a_i \sum\limits_{j|N} \mu(j) \times j^d \times (\frac{N}{j})^i$
$=\sum\limits_{i=1}^{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=1}^{d+1} a_i \times N^i \prod\limits_{j=1}^{w} (1-p_j^{d-1-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 }
来源:https://www.cnblogs.com/hzoi-DeepinC/p/12013657.html
