首页 > 其他分享 >P2822 [NOIP2016 提高组] 组合数问题

P2822 [NOIP2016 提高组] 组合数问题

时间:2022-09-23 00:57:24浏览次数:81  
标签:NOIP2016 组合 取模 int 复杂度 P2822 预处理

P2822 [NOIP2016 提高组] 组合数问题

题解

作者 岛田小雅

这是一道复杂度非常容易爆炸的问题。

我看到这题的第一眼,第一反应是直接按照公式暴力跑。我们看一眼数据范围。如果直接算,复杂度是 \(O(t(nm)^2)+X>2\times{10^{10}}\)。肯定不能用公式。

既然数据那么大,我们应该想到预处理一些数据,让每个测试点都能用,从而避免一些重复的运算。那其实很容易就能想到可以把所有的组合数都算出来然后存起来。但是 \(n\) 的最大值是 \(2000\),如果直接存的话肯定存不了那么大的数。怎么办呢?其实我们可以对它进行取模,储存取模的结果。学过乘法逆元的小伙伴(比如我)这个时候眼睛一亮:哎我们是不是还要算这玩意对 \(k\) 的逆元?

大可不必,直接让它对 \(k\) 取模就行了。这样一来能被 \(k\) 整除的组合数存储结果是 \(0\),不能被整除的,结果不是 \(0\),方便我们进行计数(还有个原因是我已经把怎么算乘法逆元忘干净了)

存储的问题解决了,那么预处理的时候我们需要用题目给的公式计算吗?要知道计算阶乘是一个很庞大的工程,虽然我不知道它的具体复杂度是多少,但肯定会严重拖慢程序的速度。怎么办呢?学过高中数学的小伙伴一定知道,把组合数叠在一起可以叠出一个杨辉三角。也就是说我们用加法就可以计算出所有的组合数。

看到这里,我们已经能把大部分预处理写完了。然而还有一处需要优化,就是对答案的计数。我们需要数的是杨辉三角内一个四边形(当 \(m\leqslant{i}\) 时是个三角形)里面 \(0\) 的个数。比起每次一个一个计算,用前缀和进行预处理显然快速很多。

具体细节详见 AC 代码部分。

AC 代码

作者 岛田小雅
#include <bits/stdc++.h>
using namespace std;

const int N = 2e3+2;
int k, t;
int C[N][N], qzh[N][N];

void generate_C(int n, int m)
{
    if(!m || m==n) C[n][m] = 1;
    else C[n][m] = (C[n-1][m-1]+C[n-1][m])%k;
}

int main()
{
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> t >> k;
    for(int n = 1; n <= 2000; n++)
    {
        for(int m = 0; m <= n; m++)
        {
            generate_C(n,m);
            if(!m) qzh[n][m] = !C[n][m];
            else qzh[n][m] = qzh[n][m-1]+!C[n][m];
        }
    }
    while(t--)
    {
        int n, m;
        cin >> n >> m;
        int ans = 0;
        for(int i = 1; i <= n; i++) ans += qzh[i][min(i,m)];
        cout << ans << '\n';
    }
    return 0;
}

标签:NOIP2016,组合,取模,int,复杂度,P2822,预处理
From: https://www.cnblogs.com/CasseShimada/p/16721344.html

相关文章

  • R语言学习丨数据重塑、拆分与组合基础知识,merge、melt、cast函数介绍
    今天学习R语言中数据重塑相关基础知识,主要有merge、melt、cast函数用法示例。公众号:生信分析笔记合并数据框merge()函数能够以一列为参考合并两个不同数据框,相当于数学中......
  • 巧用自动化测试组合拳保证产品质量
    https://mp.weixin.qq.com/s/oFTqhwN2Oy1zYP2vszsY2g“如何保证质量”一直是产品或项目过程中关注的焦点,而测试是产品质量把控环节中非常关键的部分。本文结合我们的实践......
  • 组合日记-九月二十一日
    卡特兰数通项公式的生成函数推导符号约定:\(C[i],[x^i]C(x)\)表示\(C(x)\)的\(x^i\)的系数。设\(C[0]=1,C[n]=n\)对括号构成的的合法括号序列数。\[\begin{align......
  • LeetCode组合总和
    组合总和前言在上篇文章通过组合问题看透回溯法当中我们通过介绍一个组合问题,仔细地分析了组合问题的回溯过程。我们之后会继续介绍一些比较经典的回溯算法题,帮助深入彻......
  • Vue 组合式函数简介
    Vue组合式函数:export导出一个函数。函数内可以定义生命周期勾子、数据及方法,它是可复用的模块。类似Mixin混入。但比Mixin更有优势。组合式函数示例:useDemo.js impo......
  • 组合问题看透回溯法
    通过组合问题看透回溯法前言已经好久没有更新了......
  • PHP 数组合并的几种方式
    <details><summary>点击查看代码</summary>```1.array_merge()函数将一个或多个数组合并为一个数组,也可以用于重置数组键名array_merge()官方文档:https://......
  • 两目标投资组合优化
    两目标投资组合优化回报与风险Photoby帕特里克·魏森伯格on不飞溅回报与风险双目标优化问题的一个经典例子是诺贝尔经济学奖得主HarryMarkowitz提出的投资组......
  • 组合模式
    组合模式的核心思想就是:一个组织有很多子组织,而无论子组织是单独一个部门或是一个分组织。该组织都希望把它们当成一样的子组织来管理。对于分组织,只用通知分组织就可以了,......
  • Problem P24. [算法课回溯]组合问题
    采用递归遍历所有可能性,再使用剪枝减小运行时间,利用回溯,代码有注释#include<iostream>#include<bits/stdc++.h>#include<cstdio>#include<string>usingnamespace......