• 【BZOJ2137】submultiple 高斯消元求伯努利数


    【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

    题解:数据明显分为两部分,一部分pi很小,一部分K很小,需要分别处理。

    不难发现,对于$n=prodlimits_ip_i^{c_i}$,$ans=prodlimits_i(1^k+2^k+...{(c_i+1)}^k)$。这就是伯努利数的形式。

    当pi很小时,我们可以预处理出$i^k$的前缀和,然后暴力计算。当k很小时,我们知道伯努利数可以表示成一个k+1次的多项式形式,可以暴力算出前k+1个值得到k+1个方程,然后进行模意义下的高斯消元求出多项式的系数,最后将p带入多项式即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    const ll P=1000000007;
    int n,m;
    ll ans;
    ll v[80000],s[100010];
    ll A[20][20];
    inline ll rd()
    {
    	ll ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
    	return ret*f;
    }
    inline ll pm(ll x,ll y)
    {
    	x%=P;
    	ll z=1;
    	while(y)
    	{
    		if(y&1)	z=z*x%P;
    		x=x*x%P,y>>=1;
    	}
    	return z;
    }
    int main()
    {
    	n=rd(),m=rd(),ans=1;
    	int i,j,k;
    	for(i=1;i<=n;i++)	v[i]=rd();
    	if(m<=12)
    	{
    		for(i=1;i<=m+1;i++)
    		{
    			for(j=1;j<=m+1;j++)	A[i][j]=pm(i,j);
    			for(j=1;j<=i;j++)	A[i][m+2]=(A[i][m+2]+pm(j,m))%P;
    		}
    		for(i=1;i<=m+1;i++)
    		{
    			for(j=i;j<=m+1;j++)  if(A[j][i]) break;
            	if(i!=j)    for(k=i;k<=m+2;k++)  swap(A[i][k],A[j][k]);
    			ll tmp=pm(A[i][i],P-2);
    			for(k=i;k<=m+2;k++)	A[i][k]=A[i][k]*tmp%P;
    			for(j=1;j<=m+1;j++)	if(i!=j)
    			{
    				tmp=A[j][i];
    				for(k=i;k<=m+2;k++)	A[j][k]=(A[j][k]-A[i][k]*tmp%P+P)%P;
    			}
    		}
    		for(i=1;i<=n;i++)
    		{
    			ll tmp=0;
    			for(j=1;j<=m+1;j++)	tmp=(tmp+A[j][m+2]*pm(v[i]+1,j))%P;
    			ans=ans*tmp%P;
    		}
    		printf("%lld",ans);
    		return 0;
    	}
    	for(i=1;i<=100000;i++)	s[i]=(s[i-1]+pm(i,m))%P;
    	for(i=1;i<=n;i++)	ans=ans*s[v[i]+1]%P;
    	printf("%lld",ans);
    	return 0;
    }
  • 相关阅读:
    消息中间件——RabbitMQ(六)理解Exchange交换机核心概念!
    消息中间件——RabbitMQ(五)快速入门生产者与消费者,SpringBoot整合RabbitMQ!
    消息中间件——RabbitMQ(四)命令行与管控台的基本操作!
    消息中间件——RabbitMQ(三)理解RabbitMQ核心概念和AMQP协议!
    LayUI的基本使用
    Git报错:Your branch is up to date with 'origin/master'.
    Git报错:Please tell me who you are.
    Git报错:Permission denied (publickey)
    在 windows 上安装 git 2.22
    在 windows 上安装 git 2.15
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7965465.html
Copyright © 2020-2023  润新知