专栏首页数据结构与算法BZOJ2655: calc(dp 拉格朗日插值)

BZOJ2655: calc(dp 拉格朗日插值)

题意

题目链接

Sol

首先不难想到一个dp

设\(f[i][j]\)表示选了\(i\)个严格递增的数最大的数为\(j\)的方案数

转移的时候判断一下最后一个位置是否是\(j\)

\[f[i][j] = f[i][j - 1] + f[i - 1][j - 1] * j\]

for(int i = 0; i <= A; i++) f[0][i] = 1;
for(int i = 1; i <= N; i++)
    for(int j = 1; j <= A; j++) 
        f[i][j] = add(f[i][j - 1], mul(f[i - 1][j - 1], j));
cout << mul(f[N][A], fac[N]);

发现还是不好搞,把转移拆开

\(f[i][j] = \sum_{k = 0}^{j - 1} f[i - 1][k] * (k + 1)\)

这个转移就非常有意思了

我们如果把\(i\)看成列,\(k\)看成行,那么转移的时候实际上就是先对第\(k\)行乘上一个系数\(k\),然后再求和

如果我们把第\(i - 1\)列看成一个\(t\)次多项式,显然第\(i\)列是一个\(t+2\)次多项式(求和算一次,乘系数算一次)

这样的话第\(i\)列就是一个最高\(2i+1\)次多项式

插一插就好了

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 10001;
int A, N, Lim, mod, f[501][MAXN], fac[MAXN], y[MAXN];
int add(int x, int y) {
    if(x + y < 0) return x + y + mod;
    return x + y >= mod ? x + y - mod : x + y;
}
void add2(int &x, int y) {
    if(x + y < 0) x = (x + y + mod);
    else x = (x + y >= mod ? x + y - mod : x + y);
}
int mul(int x, int y) {
    return 1ll * x * y % mod;
}
int fp(int a, int p) {
    int base = 1;
    while(p) {
        if(p & 1) base = mul(base, a);
        a = mul(a, a); p >>= 1;
    }
    return base;
}
int Large(int *y, int k) {
    static int x[MAXN], ans = 0;
    for(int i = 1; i <= Lim; i++) x[i] = i;
    for(int i = 0; i <= Lim; i++) {
        int up = y[i], down = 1;
        for(int j = 0; j <= Lim; j++) {
            if(i == j) continue;
            up = mul(up, add(k, -x[j]));
            down = mul(down, add(x[i], -x[j]));
        }
        add2(ans, mul(up, fp(down, mod - 2)));
    }
    return ans;
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("a.in", "r", stdin);
   // freopen("a.out", "w", stdout);
#endif
    cin >> A >> N >> mod; Lim = 2 * N + 1;
    fac[0] = 1; for(int i = 1; i <= N; i++) fac[i] = mul(i, fac[i - 1]);
    for(int i = 0; i <= Lim; i++) f[0][i] = 1;
    for(int i = 1; i <= N; i++) {
        for(int j = 1; j <= Lim; j++) {
            f[i][j] = add(f[i][j - 1], mul(f[i - 1][j - 1], j));
        }
    }
    for(int i = 0; i <= Lim; i++) y[i] = f[N][i];
    cout << mul(Large(y, A), fac[N]);
    return 0;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • hadoop2-HBase的Java API操作

    Hbase提供了丰富的Java API,以及线程池操作,下面我用线程池来展示一下使用Java API操作Hbase。

    Hongten
  • hadoop集群安装

    分布式安装 修改IP地址和主机名(主机名可以不用修改) hadoop1.com 192.168.213.146 192.168.213.255 255.255....

    张泽旭
  • Flume定制实战——日志平台架构解析

    agent本身是一个Java进程,运行在日志收集节点—所谓日志收集节点就是服务器节点。

    高广超
  • 面向数据架构的云演变

    现代数据架构的概念在过去的10多年里发生了巨大的变化,具体可以参见公众号“补天遗石”的《从数据仓库到数据湖——浅谈数据架构演进》一文。

    半吊子全栈工匠
  • 大数据概念:史上最全大数据解析

    现如今,我们身边很多人对一些热门的新技术、新趋势往往趋之若鹜却又很难说得透彻,比如大数据,如果被问大数据和你有什么关系,估计很少能说出一二三来。究其原因,一是因...

    用户2292346
  • Elasticsearch、MongoDB和Hadoop比较

    IT界在过去几年中出现了一个有趣的现象。很多新的技术出现并立即拥抱了“大数据”。稍微老一点的技术也会将大数据添进自己的特性,避免落大部队太远,我们看到了不同技术...

    哲洛不闹
  • 【不用等中年危机了,这次动静太大你瞧好了】大军即将进入...

    随着大数据时代的到来,【这次国~家~教~育~部的改革要动真格了】,JAVA程序员们仅有的一点点竞争力很快就不复存在,为什么这么说呢?

    java进阶架构师
  • MapReduce:N keys,N files

    MapReduce中,不管是map阶段还是reduce阶段,二者的输入和输出都是key,value类型的值。现在有个需求是根据map阶段返回值key的个数,生成...

    YG
  • 互联网后台开发需要掌握什么?

    互联网后台开发,通常意味着分布式、大数据,涉及到高性能、系统容灾、数据容灾、高可用性、数据一致性等。自从2008年Hadoop在华夏大地蓬勃发展,开源如火山爆...

    一见
  • 使用Atlas进行元数据管理之Atlas简介

    谈到数据治理,自然离不开元数据。元数据(Metadata),用一句话定义就是:描述数据的数据。元数据打通了数据源、数据仓库、数据应用,记录了数据从产生到消费的全...

    mantou

扫码关注云+社区

领取腾讯云代金券