标签:插值法 Luogu mo P4463 times int cdots na1 include
题目描述
一个序列a_1,\cdots,a_na1,⋯,an是合法的,当且仅当:
长度为给定的nn。
a_1,\cdots,a_na1,⋯,an都是[1,A][1,A]中的整数。
a_1,\cdots,a_na1,⋯,an互不相等。
一个序列的值定义为它里面所有数的乘积,即a_1\times a_2\times\cdots\times a_na1×a2×⋯×an。
求所有不同合法序列的值的和。
两个序列不同当且仅当他们任意一位不一样。
输出答案对一个数modmod取余的结果。
题解
- 我们可以先统计出数值递增的贡献和,为贡献和*n!
- 设f[i][j]表示前i个数选的值都小于等于j的贡献和,转移为f[i][j]=f[i-1][j-]*j+f[i][j-1]
- 然后呢我们就可以暴力做拉格朗日插值法就好了
代码
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define ll long long 5 int a,n,mo,res,m,f[510][1010],y[1010]; 6 using namespace std; 7 int ksm(int a,int b) { int r=1; for (;b;b>>=1,a=1ll*a*a%mo) if (b&1) r=1ll*r*a%mo; return r; } 8 int change(int x) 9 { 10 if (x>=1&&x<=m) return y[x]; 11 int r=0; 12 for (int i=1;i<=m;i++) 13 { 14 int p=y[i],q=1; 15 for (int j=1;j<=m;j++) if (i!=j) p=1ll*p*(x-j)%mo,q=1ll*q*(i-j)%mo; 16 p<0?p+=mo:0,q<0?q+=mo:0,r=(r+1ll*p*ksm(q,mo-2))%mo; 17 } 18 return r; 19 } 20 int main() 21 { 22 scanf("%d%d%d",&a,&n,&mo),res=1,m=2*n+1; 23 for (int i=1;i<=n;i++) res=1ll*res*i%mo; 24 for (int i=0;i<=m;i++) f[0][i]=1; 25 for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) f[i][j]=(1ll*f[i-1][j-1]*j+f[i][j-1])%mo; 26 for (int i=1;i<=m;i++) y[i]=f[n][i]; 27 printf("%lld",1ll*res*change(a)%mo); 28 }
标签:插值法,Luogu,mo,P4463,times,int,cdots,na1,include 来源: https://www.cnblogs.com/Comfortable/p/11269333.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。