题目大意
定义$f_d(n)=\sum\limits_{i=1}^ni^d[\gcd(i,n)=1]$
题目分析
这是一个很经典的问题,这里有一份写的很好的题解。
首先考虑对原式进行莫比乌斯反演。
令$h(n)=\sum\limits_{i=1}^ni^d$,我们称$h$为自然数幂和。
自然数幂和有很多种解法,并且其可以表示为多项式形式。
注意自然数幂和无常数项。
本题可以用是$O(d^3)$的高斯消元,$O(d^2)$的拉格朗日插值法,$O(d\log d)$的伯努利数,$O(1)$的打表求出$a_i$,这样就可以将自然数幂和用多项式表示出来。
在时空间允许的范围内,一般还是选择打表和高斯消元,其余两个太复杂了。
因此,我们可以得到$a_i$的系数,原式变为:
令:
原式变为:
令$r(k)=\mu(k)k^d$,则:
这是两个积性函数的狄利克雷卷积,因此$g_i(n)$是积性函数。
但因为$g_i(n)$不是完全积性函数,故对$n$作质因数分解。
因此我们只需要考虑求出$g_i(p_j^{q_j})$即可。
对$\mu(p^j)p^{jd}(\frac{p^q}{p^j})^i$讨论:
- 当$j=0$时,$\mu(p^j)=\mu(1)=1$,该式为$p^{qi}$
- 当$j=1$时,$\mu(p^j)=\mu(p)=-1$,该式为$-p^{qi+d-i}$
- 否则,$\mu(p^j)=0$,该式为$0$
因此,$g_i(p^q)=p^{qi}-p^{qi+d-i}$,可以$O(w\log q_i)$求出。
总复杂度为$O(d^3+dw\log q_i)$或$O(dw\log q_i)$。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| #include<algorithm> #include<iostream> #include<iomanip> #include<cstring> #include<cstdlib> #include<climits> #include<vector> #include<cstdio> #include<cmath> #include<queue> using namespace std;
typedef long long LL;
inline const LL Get_Int() { LL num=0,bj=1; char x=getchar(); while(x<'0'||x>'9') { if(x=='-')bj=-1; x=getchar(); } while(x>='0'&&x<='9') { num=num*10+x-'0'; x=getchar(); } return num*bj; }
const int maxd=105,maxw=1005; const LL mod=1e9+7;
LL d,w,a[maxd][maxd],ans[maxd],p[maxw],up[maxw];
LL Quick_Pow(LL a,LL b) { LL sum=1; for(; b; b>>=1,a=a*a%mod)if(b&1)sum=sum*a%mod; return sum; }
LL inv(LL x) { return Quick_Pow(x,mod-2); }
void Simplify(int n,int x) { if(!a[x][x]) { for(int i=x+1; i<=n; i++) if(a[i][x]) { for(int j=1; j<=n+1; j++)swap(a[i][j],a[x][j]); break; } } LL tmp=inv(a[x][x]); for(int i=x+1; i<=n; i++) { if(!a[i][x])continue; LL mul=a[i][x]*tmp%mod; for(int j=x; j<=n+1; j++)a[i][j]=(a[i][j]-a[x][j]*mul%mod+mod)%mod; } }
void Gauss(int n) { for(int i=1; i<=n; i++)Simplify(n,i); for(int i=n; i>=1; i--) { for(int j=i+1; j<=n; j++)a[i][n+1]=(a[i][n+1]-a[i][j]*ans[j]%mod+mod)%mod; ans[i]=a[i][n+1]*inv(a[i][i])%mod; } }
int main() { d=Get_Int(); w=Get_Int(); for(int i=1; i<=w; i++) { p[i]=Get_Int(); up[i]=Get_Int(); } LL sum=0; for(int i=1; i<=d+1; i++) { a[i][1]=i; for(int j=2; j<=d+1; j++)a[i][j]=a[i][j-1]*i%mod; a[i][d+2]=(a[i-1][d+2]+Quick_Pow(i,d))%mod; } Gauss(d+1); LL Ans=0; for(int i=1; i<=d+1; i++) { LL sum=1; for(int j=1; j<=w; j++) { LL tmp=(Quick_Pow(p[j],up[j]*i)-Quick_Pow(p[j],up[j]*i+d-i)+mod)%mod; sum=sum*tmp%mod; } Ans=(Ans+ans[i]*sum%mod)%mod; } printf("%lld\n",Ans); return 0; }
|