zoukankan      html  css  js  c++  java
  • bzoj3601 一个人的数论 (拉格朗日插值求系数)

    题目链接:bzoj3601 一个人的数论

    Description

    有一天hjy96想到了一个数论问题:

    对于一个非负整数d和一个正整数n,定义fa(n)为所有小于n且与n互质的正整数的d次方之和。如(f_3(10) = 1^3+3^3+7^3+ 9^3)

    现给定d,n,求fa(n)的值。输出答案对(10^9+7)取模后的结果。

    hjy96当然知道怎么做啦!但是他想考考你.....

    Input

    由于n可能很大,我们给出n的质因数分解式。

    [n=prodlimits_{i=1}^wp_i^{alpha_i} ]

    第一行有用空格隔开的一个非负整数d,一个正整数w。

    接下来w行,每行有两个用空格隔开的正整数(p_i,alpha_i)。(保证(p_i)为素数且互不相同)

    Output

    一行,一个非负整数表示(f_d(n))(10^9+7)取模后的结果。

    Sample Input

    3 2
    2 1
    5 1
    

    Sample Output

    1100
    

    数据范围与约定

    对于所有数据 (1le dle 100,1 le w le 1000,2 le p_i le 10^9,1 le alpha_i le 10^9.)

    Solution

    由题可知

    [ans=sumlimits_{i=1}^n[gcd(i,n)=1]i^d ]

    推一下

    [ans=sumlimits_{i=1}^n[gcd(i,n)=1]i^d\ =sumlimits_{i=1}^nsumlimits_{t|x且t|n}mu(t)i^d\ =sumlimits_{t|n}mu(t)sumlimits_{i=1}^{frac{n}{t}}(i imes t)^d\ =sumlimits_{t|n}mu(t)t^dsumlimits_{i=1}^{frac{n}{t}}i^d\ ]

    (sumlimits_{i=1}^{frac{n}{t}}i^d可以表示为一个关于frac{n}{t}的d+1次多项式sumlimits_{i=0}^{d+1}f_i(frac{n}{t})^i)
    (f_i)可以用拉格朗日插值或高斯消元求出(我用的是拉格朗日)​

    [ herefore ans=sumlimits_{t|n}mu(t)t^dsumlimits_{i=0}^{d+1}f_i(frac{n}{t})^i\ =sumlimits_{t|n}mu(t)sumlimits_{i=0}^{d+1}f_in^it^{d-i}\ =sumlimits_{i=0}^{d+1}sumlimits_{t|n}mu(t)f_in^it^{d-i}\ =sumlimits_{i=0}^{d+1}f_in^isumlimits_{t|n}mu(t)t^{d-i}\ ]

    容易发现(sumlimits_{t|n}mu(t)t^{d-i})是一个积性函数

    (F(n)=sumlimits_{t|n}mu(t)t^{d-i})

    则有(F(n)=prodlimits_{i=1}^{w}F(p_i^{alpha_i}))

    (F(p_i^{alpha_i}))显然等于(1-p_i^{d-i})

    [ herefore ans= sumlimits_{i=0}^{d+1}f_in^iprodlimits_{i=1}^{w}(1-p_i^{d-i})\ ]

    Code

    #include<bits/stdc++.h>
    const int N=1005;
    const int mod=1e9+7;
    int Pow(int x,int f=mod-2){
    	int re=1;
    	while(f){
    		if(f&1)re=1ll*re*x%mod;
    		f>>=1;
    		x=1ll*x*x%mod;
    	}
    	return re;
    }
    namespace Lagrange{
    	int inv[N],f_[N],f[N],y[N],tmp[N];
    	void Solve(int n){
    		for(int i=1;i<=n;i++){
    			int div=1,lst=0;
    			for(int j=1;j<=n;j++)
    				if(i!=j)div=1ll*div*(mod+i-j)%mod;
    			div=1ll*y[i]*Pow(div)%mod;
    			for(int j=0;j<n;j++){
    				tmp[j]=1ll*(lst+mod-f_[j])*inv[i]%mod;
    				f[j]=(f[j]+(1ll*div*tmp[j]%mod))%mod;
    				lst=tmp[j];
    			}
    		}
    	}
    	void Pre(int d){
    		f_[0]=1;
    		for(int i=1;i<=d+2;std::swap(f_,tmp),i++){
    			tmp[0]=0,inv[i]=Pow(i);
    			for(int j=1;j<=i;j++)tmp[j]=f_[j-1];
    			for(int j=0;j<=i;j++)tmp[j]=(tmp[j]+(1ll*f_[j]*(mod-i)%mod))%mod;
    		}
    		for(int i=1;i<=d+2;i++)y[i]=(y[i-1]+Pow(i,d))%mod;
    	}
    }
    int H(int t,int p){
    	if(t<0)return (1+mod-Pow(Pow(p,-t)))%mod;
    	return (1+mod-Pow(p,t))%mod;
    }
    int d,w,a[N],p[N],ans=0;
    signed main(){
    	using namespace Lagrange;
    	scanf("%d%d",&d,&w);
    	for(int i=1;i<=w;i++)scanf("%d%d",p+i,a+i);
    	Pre(d);
    	Solve(d+2);
    	int pown=1;
    	for(int i=1;i<=d+1;i++){
    		int tmp=1;
    		for(int j=1;j<=w;j++){
    			pown=1ll*pown*Pow(p[j],a[j])%mod;
    			tmp=1ll*tmp*H(d-i,p[j])%mod;
    		}
    		ans=(ans+(1ll*f[i]*pown%mod*tmp%mod))%mod;
    	}
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    Python configparser模块
    Python OS,shutil模块
    一、操作系统基础
    Python 序列化
    Python 验证码生产程序和进度条程序
    SaltStack 实践课程二 PHP+NGINX
    Android攻城狮数据存储之文件存储
    Android攻城狮数据存储之SQLite数据库简介
    Android攻城狮数据存储之SharedPreferences
    Android攻城狮读取了JSON实现图文混排
  • 原文地址:https://www.cnblogs.com/nlKOG/p/10838973.html
Copyright © 2011-2022 走看看