BZOJ3601 一个人的数论【莫比乌斯反演+拉格朗日插值求自然数幂和多项式系数】

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/C20181220_xiang_m_y/article/details/102640911

题目描述:

在这里插入图片描述

题目分析:

这似乎是官方题解:题解1
这是比较详细的题解:题解2

拉格朗日插值求系数调错调了1h+…

#include<bits/stdc++.h>
#define maxn 105
using namespace std;
const int mod = 1e9+7;
int d,n,a[maxn],s[maxn],f[maxn],len;
inline int Pow(int a,int b){
	int s=1;
	for(;b;b>>=1,a=1ll*a*a%mod) b&1&&(s=1ll*s*a%mod);
	return s;
}
inline void Mul(int *f,int t){//f*(x-t)
	for(int i=++len;i>0;i--) f[i]=((i?f[i-1]:0)-1ll*t*f[i])%mod;
}
inline void Div(int *f,int t){//f/(x-t)
	int pre=0,now;
	for(int i=len--;i>=0;i--,pre=now) now=f[i],f[i]=(pre+1ll*f[i+1]*t)%mod;
}
void Lagrange_Polynomial(){
	f[0]=1; int D=1,Y=0;
	for(int i=0;i<=d+1;i++) Mul(f,i);
	for(int i=1;i<=d+1;i++) D=1ll*D*(0-i)%mod; D=Pow(D,mod-2);
	for(int i=0;i<=d+1;i++){
		Div(f,i),Y=(Y+Pow(i,d))%mod;
		for(int j=0;j<=d+1;j++) a[j]=(a[j]+1ll*Y*D%mod*f[j])%mod;
		Mul(f,i),D=1ll*D*(i-(d+1))%mod*Pow(i+1,mod-2)%mod;
	}
}
int main()
{
	scanf("%d%d",&d,&n);
	Lagrange_Polynomial();
	for(int i=1;i<=d+1;i++) s[i]=1;
	for(int o=1,p,k;o<=n;o++){
		scanf("%d%d",&p,&k);
		for(int i=0;i<=d+1;i++)
			s[i]=1ll*s[i]*(Pow(p,1ll*k*i%(mod-1))-Pow(p,(1ll*k*i+d-i)%(mod-1)))%mod;
	}
	int ans=0;
	for(int i=0;i<=d+1;i++) ans=(ans+1ll*a[i]*s[i])%mod;
	printf("%d\n",(ans+mod)%mod);
}

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/102640911
今日推荐