[BZOJ2655]calc(拉格朗日插值法+DP)

时间:2022-09-09 11:46:49

2655: calc

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 428  Solved: 246
[Submit][Status][Discuss]

Description

  一个序列a1,...,an是合法的,当且仅当:
  长度为给定的n。
  a1,...,an都是[1,A]中的整数。
  a1,...,an互不相等。
  一个序列的值定义为它里面所有数的乘积,即a1a2...an。
  求所有不同合法序列的值的和。
  两个序列不同当且仅当他们任意一位不一样。
  输出答案对一个数mod取余的结果。

Input

  一行3个数,A,n,mod。意义为上面所说的。

Output

  一行结果。

Sample Input

9 7 10007

Sample Output

3611

HINT

数据规模和约定

  0:A<=10,n<=10。

  1..3:A<=1000,n<=20.

  4..9:A<=10^9,n<=20

  10..19:A<=10^9,n<=500。

  全部:mod<=10^9,并且mod为素数,mod>A>n+1

Source

[Submit][Status][Discuss]

https://blog.csdn.net/qq_20669971/article/details/52790835

先列出DP方程,f[i][j]表示i个元素选j个进排列的总贡献,则f[i][j]=f[i-1][j-1]*i*j+f[i-1][j]。(这里也可以把n!提出来)

直接DP肯定不行,然后我们可以发现f[i][j]实际上是关于i的高次多项式,现在要确定是几次多项式。

第一种方法:f[i][i]=(i!)^2,根据递推式求得f[i][j]是2j次的。

https://www.cnblogs.com/xiao-ju-ruo-xjr/p/8510924.html

第二种方法:打表发现系数中i的次数和i本身的次数都为j。

https://blog.csdn.net/ez_yww/article/details/77221338

所以确定是2j次的(当然如果不想确定就多放几次也没关系)

这样我们可以用拉格朗日插值法先求出2n个点的f[x_i][n],拟合出多项式后将A代入即可(直接现场代入就好)

 #include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const int N=;
int f[N<<][N],x,n,mod,ans,m; int inv(int a){
int res=,b=mod-;
for (; b; a=1ll*a*a%mod,b>>=)
if (b & ) res=1ll*res*a%mod;
return res;
} int main(){
freopen("bzoj2655.in","r",stdin);
freopen("bzoj2655.out","w",stdout);
scanf("%d%d%d",&x,&n,&mod); f[][]=; m=*n+;
rep(i,,m) { f[i][]=; rep(j,,n) f[i][j]=(f[i-][j]+1ll*i*f[i-][j-])%mod; }
rep(i,,m){
int a=f[i][n],b=;
rep(j,,m) if (i!=j) a=1ll*a*(x-j)%mod,b=1ll*b*(i-j)%mod;
a=1ll*a*inv(b)%mod; ans=(ans+a)%mod;
}
rep(i,,n) ans=1ll*ans*i%mod;
printf("%d\n",(ans+mod)%mod);
return ;
}

可以O(m)插值,预处理一些东西就好(不过瓶颈在于DP所以无所谓)

边界考虑清楚。

 #include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const int N=;
int x,n,mod,ans,m,f[N<<][N],pre[N<<],suf[N<<],fac[N<<],fin[N<<]; int inv(int a){
int res=,b=mod-;
for (; b; a=1ll*a*a%mod,b>>=)
if (b & ) res=1ll*res*a%mod;
return res;
} int main(){
freopen("bzoj2655.in","r",stdin);
freopen("bzoj2655.out","w",stdout);
scanf("%d%d%d",&x,&n,&mod); m=*n+;
rep(i,,m) f[i][]=;
rep(i,,m) rep(j,,n) f[i][j]=(f[i-][j]+1ll*i*f[i-][j-])%mod;
pre[]=; rep(i,,m) pre[i]=1ll*pre[i-]*(x-i)%mod;//(x-1)*(x-2)*...*(x-i)
suf[]=(x-m)%mod; rep(i,,m) suf[i]=1ll*suf[i-]*(x-m+i)%mod;//(x-m)*(x-m+1)*...(x-m+i)
fac[]=; rep(i,,m) fac[i]=1ll*fac[i-]*i%mod;//1*2*...*i
fin[m]=inv(fac[m]); for (int i=m-; ~i; i--) fin[i]=1ll*fin[i+]*(i+)%mod;//1/(1*2*...*i)
rep(i,,m){
int a=1ll*f[i][n]*pre[i-]%mod*((i==m)?:suf[m-i-])%mod;
int b=1ll*fin[i-]%mod*fin[m-i]*(((m-i)&)?-:)%mod;
ans=(ans+1ll*a*b)%mod;
}
rep(i,,n) ans=1ll*ans*i%mod;
printf("%d\n",(ans+mod)%mod);
return ;
}

以及另一道用拉格朗日插值法简化的题目:[BZOJ4559][JLOI2016]成绩比较

http://www.cnblogs.com/nbwzyzngyl/p/8394921.html

[BZOJ2655]calc(拉格朗日插值法+DP)的更多相关文章

  1. bzoj千题计划269:bzoj2655&colon; calc &lpar;拉格朗日插值)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2655 f[i][j] 表示[1,i]里选严格递增的j个数,序列值之和 那么ans=f[A][n] * ...

  2. P4463 &lbrack;集训队互测2012&rsqb; calc 拉格朗日插值 dp 多项式分析

    LINK:calc 容易得到一个nk的dp做法 同时发现走不通了 此时可以考虑暴力生成函数. 不过化简那套不太熟 且最后需要求多项式幂级数及多项式exp等难写的东西. 这里考虑观察优化dp的做法. 不 ...

  3. BZOJ2655 Calc - dp 拉格朗日插值法

    BZOJ2655 Calc 参考 题意: 给定n,m,mod,问在对mod取模的背景下,从[1,m]中选出n个数相乘可以得到的总和为多少. 思路: 首先可以发现dp方程 ,假定dp[m][n]表示从[ ...

  4. &lbrack;国家集训队&rsqb; calc&lpar;动规&plus;拉格朗日插值法&rpar;

    题目 P4463 [国家集训队] calc 集训队的题目真是做不动呀\(\%>\_<\%\) 朴素方程 设\(f_{i,j}\)为前\(i\)个数值域\([1,j]\),且序列递增的总贡献 ...

  5. bzoj4559&lbrack;JLoi2016&rsqb;成绩比较 容斥&plus;拉格朗日插值法

    4559: [JLoi2016]成绩比较 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 261  Solved: 165[Submit][Status ...

  6. Matlab数值计算示例: 牛顿插值法、LU分解法、拉格朗日插值法、牛顿插值法

    本文源于一次课题作业,部分自己写的,部分借用了网上的demo 牛顿迭代法(1) x=1:0.01:2; y=x.^3-x.^2+sin(x)-1; plot(x,y,'linewidth',2);gr ...

  7. 拉格朗日插值法——用Python进行数值计算

    插值法的伟大作用我就不说了.... 那么贴代码? 首先说一下下面几点: 1. 已有的数据样本被称之为 "插值节点" 2. 对于特定插值节点,它所对应的插值函数是必定存在且唯一的(关 ...

  8. CPP&amp&semi;MATLAB实现拉格朗日插值法

    开始学习MATLAB(R和Python先放一放...),老师推荐一本书,看完基础就是各种算法...首先是各种插值.先说拉格朗日插值法,这原理楼主完全不懂的,查的*,好久才看懂.那里讲的很详细,这 ...

  9. codeforces 622F&period; The Sum of the k-th Powers 拉格朗日插值法

    题目链接 求sigma(i : 1 to n)i^k. 为了做这个题这两天真是补了不少数论, 之前连乘法逆元都不知道... 关于拉格朗日插值法, 我是看的这里http://www.guokr.com/ ...

随机推荐

  1. C&num; 调用网易&OpenCurlyDoubleQuote;易盾” Web API

    易盾是网易推出的反垃圾云服务,最近准备试用一下,但发现api文档中只提供了Java, Python, PHP的示例代码,却没有C#的示例代码,于是参照Java示例代码用C#实现了一下. Java中用H ...

  2. 手动给控制器添加xib

    UIViewController绑定xib界面可视化,有两种方式: 1.第一种(自动化),在创建控制器时,勾选xib选项. 2.第二种手动创建一个Xib,然后再手动绑定到对应的控制器上

  3. Oracle的sqlnet&period;ora与password文件试验

    先看有没有sqlnet.ora [oracle@localhost ~]$ cd $ORACLE_HOME[oracle@localhost dbhome_1]$ cd network[oracle@ ...

  4. C语言计算开方

    C语言里面有sqrt可以计算开平方根,但似乎想要计算开任意次方根的话却没有一个固定的函数,自己写算法也蛮啰嗦的…… 其实啊,巧妙使用pow函数就可以实现需求. C语言库函数pow的原型声明如下: #i ...

  5. 无法解决 equal to 运算中 &amp&semi;quot&semi;Chinese&lowbar;PRC&lowbar;CI&lowbar;AS&amp&semi;quot&semi; 和 &amp&semi;quot&semi;SQL&lowbar;Latin1&lowbar;General&lowbar;CP1&lowbar;CI&lowbar;AS&amp&semi;quot&semi; 之间的排序规则冲突。

    什么是排序规则(collation) 关于SQL Server的排序规则,估计大家都不陌生,在创建数据库时我们经常要选择一种排序规则(conllation),一般我们会留意到每一种语言的排序规则都有许 ...

  6. html网页中 点击按钮页面跳转

    在html页面中 实现点击按钮页面跳转.语句如下: <input type="button" value="跳转" onClick="windo ...

  7. shrio初体验(2)Realm

    Realm:域,Shiro从从Realm获取安全数据(如用户.角色.权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法:也需 ...

  8. Git协同工作流介绍

    git相关的文章和教程非常多,但是系统介绍和了解工作流的人并不多,在使用过程中用错或用偏的也不少,这里分享的是,假设你已经入门的情况下,我们如何去选择适合团队需要的工作流. git优势 这里先唠叨gi ...

  9. 3ci

  10. PG数据库基本命令——查询(笔记)

    1.插入数据(insert 语句) 语法: INSERT INTO TABLE_NAME (column1, column2, column3,...columnN) VALUES (value1, ...