• 【BZOJ 3601】一个人的数论


    题目

    (sum_{i=1}^n[(i,n)=1]i^m)(n)非常大,以质因数分解后的形式给出。

    随手反演一波,上面那个式子就是

    [sum_{d|n}mu(d)sum_{i=1}^{frac{n}{d}}(i imes d)^m=sum_{d|n}mu(d)d^msum_{i=1}^{frac{n}{d}}i^m ]

    我们发现这有一个自然数幂次方和,众所周知这是一个(m+1)多项式,我们可以把系数插出来,之后变成了

    [sum_{d|n}mu(d)d^msum_{i=0}^{m+1}f_i(frac{n}{d})^i=sum_{i=0}^{m+1}f_isum_{d|n}mu(d)d^m(frac{n}{d})^i ]

    不妨设(g(n,i)=sum_{d|n}mu(d)d^m(frac{n}{d})^i=n^isum_{d|n}mu(d)d^{m-i}),这显然是一个积性函数;于是每个质因子是独立的,正好给出了(n)的分解式,于是算一下每个质数次幂的值就好了;

    对于(g(p^a,i))只有(mu(1),mu(p))不是0,于是单独算一下这两项就好了

    代码

    #include<bits/stdc++.h>
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    const int mod=1e9+7;
    inline int dqm(int x) {return x<0?x+mod:x;}
    inline int qm(int x) {return x>=mod?x-mod:x;}
    inline int ksm(int a,int b) {
    	int s=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)s=1ll*s*a%mod;return s;
    }
    const int maxn=1005;
    int n,m,p[maxn],w[maxn],pre[maxn];
    int f[maxn],g[maxn],h[maxn],ifac[maxn],fac[maxn];
    inline void Lagrange(int N) {
    	for(re int i=1;i<=N;i++)pre[i]=qm(pre[i-1]+ksm(i,m));
    	fac[0]=ifac[0]=g[0]=1;
    	for(re int i=1;i<=N;i++)fac[i]=1ll*fac[i-1]*i%mod;
    	ifac[N]=ksm(fac[N],mod-2);
    	for(re int i=N-1;i;--i)ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
    	for(re int i=0;i<=N;++i) 
    		for(re int j=i+1;j>=0;j--) {
    			g[j]=1ll*g[j]*dqm(-i)%mod;
    			if(j)g[j]=qm(g[j]+g[j-1]);
    		}
    	for(re int i=1;i<=N;i++) {
    		int v=1ll*pre[i]*ifac[i]%mod*ifac[N-i]%mod*((N-i)&1?mod-1:1)%mod;
    		int Inv=ksm(dqm(-i),mod-2);h[0]=1ll*g[0]*Inv%mod;
    		for(re int j=1;j<=N;j++)h[j]=1ll*dqm(g[j]-h[j-1])*Inv%mod;
    		for(re int j=0;j<=N;j++)f[j]=qm(f[j]+1ll*v*h[j]%mod);
    	}
    }
    int main() {
    	scanf("%d%d",&m,&n);Lagrange(m+1);int ans=0;
    	for(re int i=1;i<=n;i++)scanf("%d%d",&p[i],&w[i]);
    	for(re int i=1;i<=m+1;i++) {
    		int prod=1;
    		for(re int j=1;j<=n;j++) {
    			int nw=ksm(p[j],1ll*w[j]*i%(mod-1));
    			int u=(m-i+mod-1)%(mod-1);
    			prod=1ll*prod*nw%mod*dqm(1-ksm(p[j],u))%mod;
    		}
    		ans=qm(ans+1ll*f[i]*prod%mod);
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    php 快速fork出指定个子进程
    批量 kill mysql 中运行时间长的sql
    socket 发送发送HTTP请求
    Qt学习笔记常用容器
    Qt学习笔记 TableWidget使用说明和增删改操作的实现
    Qt学习笔记 线程(一)
    Qt学习笔记 QMessageBox
    Qt 学习笔记 TreeWidget 增删改
    Qt Creator 常用快捷键
    Qt学习笔记 ListWidget的增删改
  • 原文地址:https://www.cnblogs.com/asuldb/p/12264116.html
Copyright © 2020-2023  润新知