[湖北省队互测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;
}
一个人的数论

 

posted @ 2020-07-06 23:46  Fugtemypt  阅读(174)  评论(0编辑  收藏  举报