zoukankan      html  css  js  c++  java
  • 一个人的数论:莫比乌斯反演,伯努利数

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

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

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

    题意式子:

    $ sumlimits_{i=1}^{N} left[ gcd left( i,N ight) =1 ight] i^d $

    经典反演:

    $=sumlimits_{i=1}^{N} i^d sumlimits_{j|i and j|N} mu(j)$

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

    $=sumlimits_{j|N} mu(j) j^d sumlimits_{i=1}^{frac{N}{j}}i^d$

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

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

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

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

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

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

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

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

    $=sumlimits_{j|N} mu(j) j^d sumlimits_{i=0}^{d+1}(frac{N}{j})^i imes a_i$

    $=sumlimits_{i=0}^{d+1} a_i sumlimits_{j|N} mu(j) imes j^d imes  (frac{N}{j})^i$

    $=sumlimits_{i=0}^{d+1} a_i imes N^i sumlimits_{j|N} mu(j) imes j^{d-i}$

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

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

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

    式子的最终形态:

    $=sumlimits_{i=0}^{d+1} a_i imes N^i prodlimits_{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
    ",ans);
    28 }
    我直到现在才追上6个月以前的泥萌啊
  • 相关阅读:
    Nokitjs 系列-01
    栗庙科三考场路线图及过关技巧
    oracle创建库和表
    Eclipse 反编译插件安装jad
    在Eclipse中使用Maven插件 博客分类: Java相关技术
    eclipse svn安装
    eclipse tomcat内存溢出,加大内存
    eclipse如何修改dynamic web module version
    Eclipse 使用 Link 方式进行插件的安装
    eclipse中 将java项目转换为web项目 博客分类: Tomcat
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12013657.html
Copyright © 2011-2022 走看看