[国家集训队] calc
嘟嘟嘟
这道题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的更多相关文章
- [国家集训队] calc(动规+拉格朗日插值法)
题目 P4463 [国家集训队] calc 集训队的题目真是做不动呀\(\%>\_<\%\) 朴素方程 设\(f_{i,j}\)为前\(i\)个数值域\([1,j]\),且序列递增的总贡献 ...
- P4463 [国家集训队] calc(拉格朗日插值)
传送门 设\(dp[i][j]\)为考虑\(i\)个数,其中最大值不超过\(j\)的答案,那么转移为\[dp[i][j]=dp[i-1][j-1]\times i\times j+dp[i][j-1] ...
- Luogu P4463 [国家集训队] calc
WJMZBMR的题果然放在几年后看来仍然挺神,提出了一种独特的优化DP的方式 首先我们想一个暴力DP,先定下所有数的顺序(比如强制它递增),然后最后乘上\(n!\)种排列方式就是答案了 那么我们容易想 ...
- p4463 [国家集训队] calc
分析 代码 #include<bits/stdc++.h> using namespace std; ][],Ans; inline int pw(int x,int p){ ; whil ...
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 7676 Solved: 3509[Subm ...
- bzoj2152 / P2634 [国家集训队]聪聪可可(点分治)
P2634 [国家集训队]聪聪可可 淀粉质点分治板子 边权直接 mod 3 直接点分治统计出所有的符合条件的点对再和总方案数约分 至于约分.....gcd搞搞就好辣 #include<iostr ...
- [洛谷P1527] [国家集训队]矩阵乘法
洛谷题目链接:[国家集训队]矩阵乘法 题目背景 原 <补丁VS错误>请前往P2761 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入 ...
- P4827「国家集训队」 Crash 的文明世界
「国家集训队」 Crash 的文明世界 提供一种不需要脑子的方法. 其实是看洛谷讨论版看出来的( (但是全网也就这一篇这个方法的题解了) 首先这是一个关于树上路径的问题,我们可以无脑上点分治. 考虑当 ...
- BZOJ 2039: [2009国家集训队]employ人员雇佣
2039: [2009国家集训队]employ人员雇佣 Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 1369 Solved: 667[Submit ...
随机推荐
- 使用Asp.Net Core MVC 开发项目实践[第一篇:项目结构说明]
先从下图看整体项目结构: Mango.Manager: 为后台管理项目 Mango.Web: 为前台项目 Mango.Framework.Core: 为常用的基础操作类项目 Mango.Framewo ...
- [LeetCode解题报告] 502. IPO
题目描述 假设 LeetCode 即将开始其 IPO.为了以更高的价格将股票卖给风险投资公司,LeetCode希望在 IPO 之前开展一些项目以增加其资本. 由于资源有限,它只能在 IPO 之前完成最 ...
- csv文件格式说明
csv文件应用很广泛,历史也很悠久.有很多种类型的csv格式,常用的是rfc 4180定义的格式. csv文件包含一行或多行记录,每行记录中包含一个或多个字段.记录与记录之间使用换行符分隔,最后一个记 ...
- [转]angular2在运行ng serve的时候卡在95% emitting LicenseWebpackPlugin
本文转自:https://blog.csdn.net/qq919694688/article/details/80912207 放弃使用cnpm,使用yarn 1.删除node_modules (不需 ...
- 通向全栈之路(6)—无密码ssh连接
(1)在用户目录下新增一个 .ssh文件 mkdir .ssh (2)生成公钥.私钥 ssh-keygen -t rsa -b 4096 -C "mail@xxx.com" (3) ...
- windows使用笔记-安装64位windows7家庭普通版的方法
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 从msdn网站:http://msdn.itellyou.cn/ 下载<cn_windows_7_ultimate_wit ...
- python之类与类之间的关系
在我们的世界中事物和事物之间总会有一些联系. 在面向对象中. 类和类之间也可以产生相关的关系 1. 依赖关系 执行某个动作的时候. 需要xxx来帮助你完成这个操作. 此时的关系是最轻的. 随时可以 ...
- CoreCRM 开发实录 —— 基于 AntDesign 的新 UI
上一篇说到,因为有新朋友加入,对前端开发有了新的要求.原来基于 Bootstrap 的 UI 就不要了.在网上(其实是 GitHub 上)逛了几圈,最后使用了 antd-admin 这个框架做为基础模 ...
- Microsoft Dynamics CRM 9.0 OP 版本 移动端
本次OP 版本做了架调整,新的移动端基本可以满足客户需求,其内容自己可配置选择,满足了一般企业的应用处理. 具体操作如下: 1.登录APP选择应用(我使用手机浏览器) 2.打开默认应用,现在就一个木得 ...
- 语义分割的简单指南 A Simple Guide to Semantic Segmentation
语义分割是将标签分配给图像中的每个像素的过程.这与分类形成鲜明对比,其中单个标签被分配给整个图片.语义分段将同一类的多个对象视为单个实体.另一方面,实例分段将同一类的多个对象视为不同的单个对象(或实例 ...