• BZOJ2137: submultiple(生成函数,二项式定理)


    Description

    设函数g(N)表示N的约数个数。现在给出一个数M,求出所有M的约数x的g(x)的K次方和。

    Input

    第一行输入N,K。N表示M由前N小的素数组成。接下来N行,第i+1行有一个正整数Pi,表示第Ai小的素数 有 Pi次。等式:

    Output

    输出一个数,表示答案。只需输出最后答案除以1000000007的余数。

    Sample Input

    2 3
    1
    3

    Sample Output

    900
    【样例说明】
    M=2^1*3^3=54
    M的约数有1,2,3,6,9,18,27,54.约数个数分别为1,2,2,4,3,6,4,8.
    Answer=1^3+2^3+2^3+4^3+3^3+6^3+4^3+8^3=900


    编号 N K Pi<=
    1 50 3 10000
    2 50 100 10000
    3 50 20101125 10000
    4 999 17651851 100000
    5 5000 836954247 100000
    6 4687 1073741823 100000
    7 4321 123456789 100000
    8 5216 368756432 100000
    9 8080 2^31-1 100000
    10 10086 3 2^63-1
    11 64970 3 2^63-1
    12 71321 3 2^63-1
    13 350 5 2^31-1
    14 250 6 2^31-1
    15 110 7 2^31-1
    16 99 8 2^31-1
    17 80 9 2^31-1
    18 70 10 2^31-1
    19 60 11 2^31-1
    20 50 12 2^31-1

    解题思路:

    拿到题感觉一脸不可做,反正不是反演的样子。

    先来考虑一下样例:

    $2^1*3^3=54$

    考虑如何将答案分类。将贡献重新累加起来。

    首先$g(d)=sumlimits_{i=1}^{n}{(1+c_i)}$()其中$c_i$为第$i$项的次数)

    现在考虑如何将$M$的所有因数表示出来:

    以54为例

    其中每个因数可以按照2的次数分类,可以是0~1次共有2种选法。

    对于每种选法,对应的数中3的次数有0~3共4种选法。

    而对应3的每一种选法其答案都是$[(2的次数+1)*(3的次数+1)]^k$

    那么这种结果可以看做两个多项式乘积的形式,这两个多项式都是(1+2+3+...)的形式,而由于那个指数上的k是可以带入括号的。

    那么答案就变成了$f(54)=(1^3+2^3)*(1^3+2^3+3^3+4^3)=9*100=900$

    现在答案就可以解出来了,答案就变成了:

    $f(M)=prodlimits_{i=1}^{n}sumlimits_{j=1}^{p_i}{j^k}$

     n是可以枚举的,对于前45分的点,可以暴力快速幂求解。

    剩下的怎么办。

    后面的那个高次求和$sumlimits_{i=1}^{n}{i^k}$是非常公式化的,怎么可能没有公式。

    高次求和公式会形如:

    $sumlimits_{i=1}^{n}{i^k}=sumlimits_{i=1}^{k+1}{a_i*n^i}$

    所以可以这样求解(orz zwz):

    $a_1x^1+a_2x^2+...+a_{k+1}x^{k+1}+(x+1)^k=a_1(x+1)+a_2(x+1)^2+...+a_{k+1}(x+1)^{k+1}$

    二项式定理展开移项:

    $sumlimits_{i=1}^{k+1}{C_i^0x^0}+sumlimits_{i=2}^{k+1}{C_i^1x^1}+...+sumlimits_{i=k+1}^{k+1}{C_i^kx^k}=sumlimits_{i=0}^{k}{C_k^ix^i}$

    这个杨辉三角打出矩阵消元就可以解出系数了。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 typedef long long lnt;
     5 const lnt mod=(lnt)(1e9+7);
     6 lnt n,k;
     7 lnt maxs;
     8 lnt C[100][100];
     9 lnt F[200001];
    10 lnt p[200001];
    11 lnt a[1001];
    12 lnt b[100][100];
    13 lnt c[100];
    14 lnt ksm(lnt x,lnt y)
    15 {
    16     lnt ans=1;
    17     while(y)
    18     {
    19         if(y&1)ans=ans*x%mod;
    20         x=x*x%mod;
    21         y=y/2;
    22     }
    23     return ans;
    24 }
    25 lnt squ(lnt x)
    26 {
    27     return x%mod*x%mod;
    28 }
    29 int main()
    30 {
    31     scanf("%lld%lld",&n,&k);
    32     for(int i=1;i<=n;i++)
    33         scanf("%lld",&p[i]),
    34         maxs=std::max(p[i],maxs);
    35     if(maxs<=100000)
    36     {
    37         lnt ans=1;
    38         for(int i=1;i<=maxs+1;i++)F[i]=(F[i-1]+ksm(i,k))%mod;
    39         for(int i=1;i<=n;i++)ans=(ans*F[p[i]+1])%mod;
    40         printf("%lld
    ",ans);
    41         return 0;
    42     }
    43     if(k==3)
    44     {
    45         lnt ans=1;
    46         lnt Inv=ksm(4,mod-2);
    47         for(int i=1;i<=n;i++)
    48             ans=ans*squ(p[i]%mod+1)%mod*squ(p[i]%mod+2)%mod*Inv%mod;
    49         printf("%lld
    ",ans);
    50         return 0;
    51     }
    52     C[0][0]=1;
    53     for(int i=1;i<=k+1;i++)
    54     {
    55         C[i][0]=1;
    56         for(int j=1;j<=i;j++)
    57             C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    58     }
    59     for(int i=1;i<=k+1;i++)
    60     {
    61         for(int j=i;j<=k+1;j++)
    62         {
    63             b[i][j]=C[j][i-1];
    64         }
    65     }
    66     for(int i=1;i<=k+1;i++)a[i]=C[k][i-1];
    67     for(int i=k+1;i>=1;i--)
    68     {
    69         a[i]=(a[i]*ksm(b[i][i],mod-2))%mod;
    70         for(int j=i-1;j;j--)
    71         {
    72             (a[j]-=b[j][i]*a[i]%mod)%=mod;
    73         }
    74     }
    75     lnt ans=1;
    76     for(int i=1;i<=n;i++)
    77     {
    78         lnt tmp=0;
    79         for(int j=1;j<=k+1;j++)
    80             tmp=(tmp+(a[j]*ksm(p[i]%mod+1,j))%mod)%mod;
    81         ans=(ans*tmp)%mod;
    82     }
    83     printf("%lld
    ",(ans%mod+mod)%mod);
    84     return 0;
    85 }
  • 相关阅读:
    使用JS获取上一页的url地址
    禁止弹窗中蒙层底部页面跟随滚动的几种方法汇总
    一个Option请求引发的深度解析
    html li标签前面添加图标三种方法
    CSS3
    计算x
    计算圆周率
    最长公共子序列
    小字辈(左子右兄加强版)
    Excel列名和列序号转换
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10357841.html
Copyright © 2020-2023  润新知