[湖北省队互测2014] 一个人的数论
题意:
定义$f_{d}(n)$为所有小于n且与n互质的正整数的d次方之和。
给定$d,n=\prod \limits_{i=1}^{w}{p_{i}^{a_{i}}}$,求$f_{d}(n)$对$10^{9}+7$取模的值。
$d\leq 100,w\leq 1000,p_{i},a_{i}\leq 10^9$。
题解:
先简单的整理一下式子,所求式为
$f_{d}(n)=\sum \limits_{i=1}^{n}{[(i,n)=1]\times i^{d}}$
$=\sum \limits_{i=1}^{n}{i^{d} \sum \limits_{c|(i,n)}{\mu(c)}}$
$=\sum \limits_{c|n}{\mu(c) \sum \limits_{i=1}^{\frac{n}{c}}{(ic)^{d}}}$
$=\sum \limits_{c|n}{\mu(c)c^{d} \sum \limits_{i=1}^{\frac{n}{c}}{i^{d}}}$
根据伯努利数那套推论,$\sum \limits_{i=1}^{n}{i^{d}}$是一个以n为自变量的d+1次函数(多项式)。
于是我们先用$Lagrange$插值把这个多项式的系数插出来,设其为$F(x)=\sum \limits_{i=0}^{d+1}{f_i x^{i}}$。
然后继续推,所求式为
$=\sum \limits_{c|n}{\mu(c)c^{d}F(\frac{n}{c})}$
$=\sum \limits_{c|n}{\mu(c)c^{d} \sum \limits_{i=0}^{d+1}{f_i (\frac{n}{c})^{i}}}$
$=\sum \limits_{i=0}^{d+1}{f_i \sum \limits_{c|n}{\mu(c)c^{d}(\frac{n}{c})^{i}}}$
根据狄利克雷卷积那套推论,如果$F(n)=\sum \limits_{d|n}{f(d)g(\frac{n}{d})}$,且f和g都是积性函数,那么F也是积性函数。
(积性函数:若$(a,b)=1$,则$F(ab)=F(a)F(b)$)
观察一下,$\mu(c),c^{d},(\frac{n}{c})^{i}$都是积性函数。
于是我们只需要算每个$n=p_{i}^{a_{i}}$处的$\sum \limits_{c|n}{\mu(c)c^{d}(\frac{n}{c})^{i}}$,然后乘起来即可。
注意到$\mu(c)$只在$c=1,p_{i}$的时候不为0,所以有用的c就俩值,直接暴力算即可。
由于$d\leq 100$,算$f_i$的时候直接暴力算即可,总复杂度$O(d^{3}+dw\log{a_{i}})$。
(注意快速幂的时候一定不要把次数取模,不要把次数取模,不要把次数取模!TAT)
套路:
- $\sum \limits_{i=1}^{n}{i^{d}}$是一个以n为自变量的d+1次函数。
- 如果$F(n)=\sum \limits_{d|n}{f(d)g(\frac{n}{d})}$,且f和g都是积性函数,那么F也是积性函数。
- 快速幂时:一定不要把次数取模,不要把次数取模,不要把次数取模!
代码:
#include<bits/stdc++.h> #define maxn 205 #define maxm 500005 #define inf 0x7fffffff #define mod 1000000007 #define ll long long #define rint register ll #define debug(x) cerr<<#x<<": "<<x<<endl #define fgx cerr<<"--------------"<<endl #define dgx cerr<<"=============="<<endl using namespace std; struct point{ll x,y;}P[maxn]; struct poly{ ll a[maxn],n; inline void clear(){memset(a,0,sizeof(a)),n=0;} poly operator+(const poly b)const{ poly res; res.clear(),res.n=max(n,b.n); for(ll i=0;i<res.n;i++) res.a[i]=(a[i]+b.a[i])%mod; return res; } poly operator*(const poly b)const{ poly res; res.clear(),res.n=n+b.n-1; for(ll i=0;i<n;i++) for(ll j=0;j<b.n;j++) res.a[i+j]=(res.a[i+j]+a[i]*b.a[j]%mod)%mod; return res; } poly operator^(const ll b)const{ poly res; res.clear(),res.n=n; for(ll i=0;i<res.n;i++) res.a[i]=a[i]*b%mod; return res; } }; ll p[maxm],al[maxm]; inline ll read(){ ll x=0,f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } inline ll pw(ll a,ll b){ll r=1;while(b)r=(b&1)?r*a%mod:r,a=a*a%mod,b>>=1;return r;} inline ll inv(ll x){if(x<0) x+=mod; return pw(x,mod-2);} inline poly Lagrange(ll n){ for(ll i=1;i<=n+2;i++) P[i].x=i,P[i].y=(P[i-1].y+pw(i,n))%mod; poly res; res.clear(); for(ll i=1;i<=n+2;i++){ poly f; f.clear(),f.n=1,f.a[0]=1; for(ll j=1;j<=n+2;j++){ if(i==j) continue; ll xi=P[i].x,xj=P[j].x,yj=P[j].y; poly g; g.clear(),g.n=2; g.a[0]=xj*inv(xj-xi)%mod; g.a[1]=inv(xi-xj)%mod,f=f*g; } res=res+(f^P[i].y); } return res; } int main(){ //freopen("1.in","r",stdin); //freopen("sol.out","w",stdout); ll d=read(),w=read(); poly f=Lagrange(d); for(ll i=1;i<=w;i++) p[i]=read(),al[i]=read(); ll ans=0; for(ll i=0;i<=d+1;i++){ ll gi=1; for(ll j=1;j<=w;j++){ ll t1=pw(p[j],al[j]*i); ll t2=mod-pw(p[j],(d+(al[j]-1)*i)); gi=gi*(t1+t2)%mod; } ans=(ans+gi*f.a[i]%mod)%mod; } printf("%lld\n",ans); return 0; }