嘟嘟嘟




这道题dp虽然不难,但是我还是没推出来,感觉最近脑子不太好用啊。

于是就跑去问神仙gjx(全国前三!)了。(外出集训真是好)




神仙不愧是神仙,一会儿就想出来了,而且方法还比网上的题解好懂。

dp[i][j]表示用值域为[1, i]的数,凑出的所有合法序列的值的和。

然后规定序列必须是严格递增的,这样答案再乘以一个\(n!\)就行了。

转移的时候,我们考虑\(i\)这个数用不用上,于是有:\(dp[i][j] = dp[i - 1][j] +i * dp[i - 1][j - 1]\)。现在感觉这个挺好理解的,如果用上\(i\)了,\(i\)就必须放在最后面,并且答案要乘以\(i\)。

但这个复杂度\(O(nA)\)的,\(A\)太大不好办。

然后gjx大佬告诉我,这个dp式是一个关于\(j\)的\(2n\)次多项式,然后给我证了一下,但还是不太懂:

首先知道\(dp[i][1] = \frac{i * (i + 1)}{2}\),猜想这可能是一个\(2n\)次的。

然后把转移方程中的\(dp[i - 1][j]\)不断展开,得到了\(dp[i][j] = \sum _ {k = 0} ^ {i - 1} dp[k][j] *(k + 1)\)。于是发现,这是一个关于\(j\)的\(2n\)次多项式。

(感觉自己还是不太理解)




这篇题解的证明好像也不错, 应该是数学归纳法,我得学一下)




知道这是个多项式,就可以拉格朗日差值了。

注意dp的边界取值,我这里debug了好久。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 505;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
} int A, n, mod;
ll fac[maxn << 1], dp[maxn << 1][maxn]; In ll quickpow(ll a, ll b)
{
ll ret = 1;
for(; b; b >>= 1, a = a * a % mod)
if(b & 1) ret = ret * a % mod;
return ret;
} ll inv[maxn << 1], pre[maxn << 1], suf[maxn << 1];
In ll calc(int n)
{
inv[n] = quickpow(fac[n], mod - 2);
for(int i = n - 1; i >= 0; --i) inv[i] = inv[i + 1] * (i + 1) % mod;
pre[0] = A;
for(int i = 1; i <= n; ++i) pre[i] = pre[i - 1] * (A - i) % mod;
suf[n + 1] = 1;
for(int i = n; i >= 0; --i) suf[i] = suf[i + 1] * (A - i) % mod;
ll ret = 0;
for(int i = 0; i <= n; ++i)
{
ll tp = (i - 1 < 0 ? 1 : pre[i - 1]) * suf[i + 1] % mod * inv[i] % mod * inv[n - i] % mod;
if((n - i) & 1) tp = -tp;
ret = (ret + dp[i][n >> 1] * tp % mod + mod) % mod;
}
return ret;
} int main()
{
A = read(), n = read(), mod = read();
fac[1] = 1;
for(int i = 2; i <= (n << 1); ++i) fac[i] = fac[i - 1] * i % mod;
dp[0][0] = 1;
for(int i = 1; i <= (n << 1); ++i)
{
dp[i][1] = i * (i + 1) / 2;
dp[i][i] = fac[i];
for(int j = 2; j < i; ++j)
dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1] * i % mod) % mod;
}
if(A <= (n << 1)) write(dp[A][n] * fac[n] % mod), enter;
else write(calc(n << 1) * fac[n] % mod), enter;
return 0;
}

[国家集训队] calc的更多相关文章

  1. [国家集训队] calc(动规+拉格朗日插值法)

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

  2. P4463 [国家集训队] calc(拉格朗日插值)

    传送门 设\(dp[i][j]\)为考虑\(i\)个数,其中最大值不超过\(j\)的答案,那么转移为\[dp[i][j]=dp[i-1][j-1]\times i\times j+dp[i][j-1] ...

  3. Luogu P4463 [国家集训队] calc

    WJMZBMR的题果然放在几年后看来仍然挺神,提出了一种独特的优化DP的方式 首先我们想一个暴力DP,先定下所有数的顺序(比如强制它递增),然后最后乘上\(n!\)种排列方式就是答案了 那么我们容易想 ...

  4. p4463 [国家集训队] calc

    分析 代码 #include<bits/stdc++.h> using namespace std; ][],Ans; inline int pw(int x,int p){ ; whil ...

  5. BZOJ 2038: [2009国家集训队]小Z的袜子(hose)

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7676  Solved: 3509[Subm ...

  6. bzoj2152 / P2634 [国家集训队]聪聪可可(点分治)

    P2634 [国家集训队]聪聪可可 淀粉质点分治板子 边权直接 mod 3 直接点分治统计出所有的符合条件的点对再和总方案数约分 至于约分.....gcd搞搞就好辣 #include<iostr ...

  7. [洛谷P1527] [国家集训队]矩阵乘法

    洛谷题目链接:[国家集训队]矩阵乘法 题目背景 原 <补丁VS错误>请前往P2761 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入 ...

  8. P4827「国家集训队」 Crash 的文明世界

    「国家集训队」 Crash 的文明世界 提供一种不需要脑子的方法. 其实是看洛谷讨论版看出来的( (但是全网也就这一篇这个方法的题解了) 首先这是一个关于树上路径的问题,我们可以无脑上点分治. 考虑当 ...

  9. BZOJ 2039: [2009国家集训队]employ人员雇佣

    2039: [2009国家集训队]employ人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1369  Solved: 667[Submit ...

随机推荐

  1. Maven教程4(私服-nexus)

    仓库管理器也叫私服或代理仓库 仓库管理器有两个服务目的:首先它的角色是一个高度可配置的介于你的组织与公开Maven仓库之间的代理,其次它为你的组织提供了一个可部署你组织内部生成的构件的地方. 1Nex ...

  2. C# 性能优化 之 秒表 Stopwatch。

    生词解释:Diagnostics[,daɪəg'nɑstɪks] n.诊断学 using System.Diagnostics; Stopwatch sw = new Stopwatch (); sw ...

  3. [MongoDB] MongoDB增删查改

    MongoDB的三元素,数据库.集合.文档,集合就是表,文档就是行 开启MongoDB,cd切换到MongoDB的安装目录下的bin目录里,使用命令mongod 开启,参数:--dbpath 路径,把 ...

  4. 【Java深入研究】1、object类

    一.概述Object类是所有Java类的祖先.每个类都使用 Object 作为超类.所有对象(包括数组)都实现这个类的方法. 参考英文:* Class {@code Object} is the ro ...

  5. 基于Zookeeper的分布式锁

    实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...

  6. Hadoop HDFS 设计随想

    目录 引言 HDFS 数据块的设计 数据块应该设置成多大? 抽象成数据块有哪些好处? 操作块信息的命令 HDFS 中节点的设计 有几种节点类型? 用户如何访问 HDFS? 如何对 namenode 容 ...

  7. HDU5887(SummerTrainingDay01-D)

    Herbs Gathering Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  8. Mysql数据库单表查询

    1.单表查询语法 #查询数据的本质:mysql会到你本地的硬盘上找到对应的文件,然后打开文件,按照你的查询条件来找出你需要的数据.下面是完整的一个单表查询的语法 select * from,这个sel ...

  9. MySQL MySql连接数与线程池

    MySql连接数与线程池 by:授客 QQ:1033553122 连接数 1.  查看允许的最大并发连接数 SHOW VARIABLES LIKE 'max_connections'; 2.  修改最 ...

  10. NoHttp封装--03 cookie

    NoHttp请求自动维持Cookie:   1.支持Session.Cookie.临时Cookie的位置.   2.支持App重启.关机开机后继续持久化维持.   3.提供了接口,允许开发者监听Coo ...